01 · Before and afterThe pattern
// before: delete happens inside the operation; a crash or later failure orphans or breaks references
await storage.move(oldKey, newKey); await db.update(doc, { key: newKey })
// after: stage -> commit -> cleanup
await storage.copy(oldKey, newKey); stage.track(newKey) // rolled back if anything below throws
await db.transaction(tx => tx.update(doc, { key: newKey }))
afterCommit(() => storage.deleteIfUnreferenced(oldKey)) // only once nothing points at it02 · Run it on your appThe check
If your server crashes between the file upload and the database save, which of the two is left pointing at nothing?
If the honest answer is no or not sure, this is worth a look before it reaches production.