Media Cleanup: How Orphaned Files Are Handled

Media Cleanup: How Orphaned Files Are Handled

When you're running a serverless platform, every byte matters. Not just for performance, but for your wallet too. One thing I've learned while building Jottings is that the little details of file management can make a huge difference in both user experience and operational costs.

Today, I want to walk you through how Jottings handles orphaned media files—those uploads that don't quite make it into a published jot, or files you delete from a post. It's a problem most blogging platforms don't talk about, but it's surprisingly important to get right.

The Problem With Media Uploads

Let's say you're writing a post and you upload an image. You're not happy with it, so you upload another one instead. Or maybe you start composing a jot with a photo, change your mind, and abandon it without publishing.

What happens to that first image?

On some platforms, it just sits there. Taking up storage. Costing money. Forever.

This is what we call an "orphaned" file—media that was uploaded but never attached to a published jot, or was deleted when the jot was removed.

At Jottings, we solve this with a simple but elegant solution: the 6-hour grace period.

The 6-Hour Grace Period Explained

When you upload media to Jottings, it doesn't get instantly deleted if you decide not to use it. Instead, we track it. The file lives in our Cloudflare R2 storage with a status of pending.

If you use that file in a jot, great—its status changes to completed, and we track which jots it belongs to (the usedInJots array). It's safe, and it won't be cleaned up.

But if six hours pass and that media is still in pending status, it gets automatically deleted. No questions asked. No "are you sure?" dialogs. Just gone.

Why six hours? It's long enough for you to:

  • Compose a multi-part post with photos
  • Step away and come back to it later
  • Change your mind and try different images
  • Sleep on a draft before publishing

But it's short enough that we're not sitting on thousands of unused files from users who changed their minds.

Why This Matters

From a user perspective, this grace period means you can experiment freely. Upload, delete, rethink, try again. No regrets. No "oh no, I deleted that image I wanted to use."

From an operational perspective, it's beautiful simplicity:

No Wasted Storage: Abandoned uploads don't accumulate. Your storage costs stay predictable and low.

Automatic Cleanup: We have a Lambda function that runs every hour, scanning for expired pending files and deleting them from R2. No manual intervention needed.

Cost Control: Cloudflare R2 charges for storage. By cleaning up automatically, we keep costs down—which means lower prices for you.

Atomic Operations: When you delete a jot that uses media, we check if that media is used anywhere else. Only orphaned files get deleted.

How It Works Under The Hood

Every time you upload media, we create a MediaRecord in our database with:

  • File URL and metadata
  • Status (pending or completed)
  • Timestamp of upload
  • A usedInJots array (empty until you use it)

When you create a jot with that media, we update the record:

Status: pending → completed
usedInJots: [jotId]

If you add the same photo to multiple jots (yes, this is allowed), the array grows:

usedInJots: [jotId1, jotId2, jotId3]

Then, every hour, our cleanup Lambda:

  1. Queries all pending records older than 6 hours
  2. Deletes the file from R2
  3. Removes the record from our database

If you delete a jot, we check the media's usedInJots array. If it's empty after removal, the file becomes orphaned and will be cleaned up in the next cycle.

The Philosophy Behind This Design

I think a lot about what makes software feel good to use. Part of that is respecting your actions without being precious about them.

By giving you a 6-hour grace period, we're saying: "We trust you. Experiment. Make mistakes. Change your mind." But we're also being responsible with storage and costs.

This is the serverless philosophy in action. Not "set it and forget it," but rather "make systems that scale down as naturally as they scale up." No junk, no waste, no manual cleanup.

What You Should Know

A few things to keep in mind:

  • If you upload media and then immediately publish a jot using it, there's no grace period. The file is marked as completed right away and won't be deleted.
  • If you delete a jot, the media cleanup happens in the next hourly cycle, usually within minutes.
  • Media you've used in multiple jots is only deleted when it's removed from all jots.
  • The 6-hour timer resets if you somehow re-upload the same file with a different filename (unlikely, but possible).

Keeping Jottings Lean

This is part of a bigger philosophy at Jottings: keeping the platform lean and efficient. No bloat. No unnecessary features. No wasted resources.

It's why we use serverless architecture. Why we charge what we do. Why we care about orphaned files when other platforms don't.

When you write on Jottings, you're not just publishing—you're publishing efficiently. Your storage is managed. Your costs are controlled. Your content is yours.

If you're thinking about moving your blog to Jottings, or you're curious about how we manage these details, I'd love to hear from you. The small things matter, and we sweat the details so you don't have to.


Ready to publish without the storage headaches? Create your Jottings site today and experience a blogging platform built for simplicity.