DEV Community

Alisha Albert
Alisha Albert

Posted on

Delete-on-read: designing a file share that destroys itself

A dissolving contract with a padlock, illustrating delete-on-read file sharing

Most file-sharing systems are built around persistence. Upload, store, serve — and keep serving until someone remembers to delete. But there's a whole class of sharing where persistence is the bug, not the feature: one-time handoffs of sensitive files.

The pattern is simple: a link that works exactly once. Here's how to think about building it.

The core mechanic: single-use tokens

At the heart of delete-on-read is a token, not a file path. The flow:

  1. Upload stores the file and generates a random, unguessable token.
  2. The share URL contains the token — nothing else identifies the file.
  3. On first successful GET, the server streams the bytes, then immediately deletes the stored file (and any database record pointing to it).
  4. Any later request with the same token returns a "gone" state.

The deletion has to happen server-side, right after the response completes. Client-side tricks — like a page that hides the link after viewing — don't count. If the bytes are still on disk, the share isn't really view-once.

A few details that matter more than they look:

  • Stream, then delete. Don't load the whole file into memory if you can stream it. Delete the source as soon as the stream finishes, in the same request lifecycle.
  • Make tokens unguessable. UUIDs or 128-bit random values. Sequential IDs are an invitation to enumeration.
  • Treat "viewed" carefully. If the recipient's browser prefetches or a link-preview bot hits the URL, that can burn the single view. A common fix: serve an interstitial page first ("click to reveal"), and only count the actual download/view click.

Multi-file shares: the ZIP trick

Single files are the easy case. For multiple files, the cleanest approach is to bundle them into a ZIP at share time and treat the ZIP as the single view-once object. The recipient gets one download, one deletion. nowiretransfer uses exactly this approach — you can drop several files in, and they arrive as one self-deleting archive.

Generating the ZIP on upload (rather than on download) keeps the download path simple and predictable: one stream, one delete, done.

Text shares are the same shape

The pattern generalizes nicely to text. Store the snippet server-side, hand out a token URL, render the text once, delete on first render. It's the same state machine as files — the only difference is the content type. Passwords, API keys, and config snippets are the natural use case, and they benefit from the same "no residue" guarantee.

What "deleted" should mean

This is where implementations get honest or don't. True delete-on-read means:

  • The file bytes are removed from storage (not just unlinked from a database row).
  • Backups and caches don't quietly keep a copy around past its intended life.
  • There's no "recently deleted" grace period that extends the exposure window.

If you're evaluating a view-once tool rather than building one, these are the questions worth asking. A tool that keeps files in a trash folder for 30 days isn't view-once — it's a file host with a countdown timer.

Why this is worth building (or using)

Delete-on-read is a small idea with an outsized effect on how people share sensitive things. It removes the whole category of "I forgot that link was still live." The UX is almost nothing — upload, share, done — because the security model is the absence of state, not the presence of more controls.

If you want to see the pattern in action, nowiretransfer is a clean example: free, no signup, files and text that delete themselves after one view, multi-file ZIP packaging. It's a good reference for how little UI this pattern actually needs.

The broader lesson: sometimes the best data retention policy is not having the data at all.

Top comments (0)