Skip to content

Delayed Delete Example

In this example we implement a delayed delete functionality with un-delete option. This way we get rid of user data for real, so we are GDPR compliant and don't risk leaking something that user thought he has deleted. While also giving him 1 day to undo his action in case he has deleted something by accident.

Architectural overview

We will use a deleted flag on our entity to hide if from UI. We need to filter them out in all the places we fetch entities. Real deletion of item will be pushed to the deleteNote queue and processed in 24 hours. If in the meantime user decides to undo his action we remove deleted flag and remove item from queue by key.

Code example

ts
import lq from '@dayone-labs/lambda-queue-express'
import { hoursToMilliseconds } from 'date-fns'
import './models'

const deleteNoteQueue = lq.queue(
  '/deleteNote',
  async (event: { noteId: NoteId }) => {
    await noteRepository.delete(event.noteId)
  },
  //Delete for real after 24 hours
  { delay: hoursToMilliseconds(24) }
)

const deleteNote = async (noteId: NoteId) => {
  const note = await noteRepository.fetch(noteId)
  //Mark as deleted, so it won't show up in UI
  note.deleted = true
  noteRepository.save(note)
  await deleteNoteQueue.push({ noteId }, { key: noteId })
}
const undeleteNote = async (noteId: NoteId) => {
  const note = await noteRepository.fetch(noteId)
  //Remove from queue, so it's not deleted
  await deleteNoteQueue.deleteByKey(noteId)
  //Remove deleted flag, so it will show up in UI again
  note.deleted = false
  noteRepository.save(note)
}

//Queue is an Express router, just mount it with app.use(queue)
export default {
  route: deleteNoteQueue,
  deleteNote,
  undeleteNote,
}

Remarks

TIP

Another common pattern to handle deleted items is to, instead of using deleted flag, move items to deleted_notes table or collection and move it back when un-deleted. This has few advantages over the flag:

  • Real data is not polluted with deleted items, improving query performance.
  • There's no need to filter out deleted items in application logic.
  • You can skip deleted items from long term backups.
  • A different storage strategy can be used for deleted and live items (table partitions, cheaper storage, etc.)

All examples are licensed under MIT. You can use them for free in your projects.