Rent the Storage, Hold the Keys
My Dropbox plan cost $119.88 a year for 2 TB. When I finally looked, it held 70 GB in about 16,600 files. That is 3.4% of what I was paying for. The renewal was due in late November, so there was a deadline.
I moved it to Cloudflare R2, a storage service you pay for by the gigabyte. It now costs about a dollar a month instead of ten. That’s the headline, but it isn’t the interesting part. The interesting part is what I decided not to build, and what changed about who controls access to the files.
What I actually used Dropbox for
Every decision followed from this, so it’s worth being exact.
- One folder is live. My consulting work, about 700 files and half a gigabyte, is edited on two machines and needs two-way sync.
- Everything else is an archive. Written once, read rarely, never edited. Camera uploads alone were 40 GB, about 63% of everything stored.
- Phone access mattered. Looking up a document or a photo from my phone was something I did, and the Dropbox app was the only thing giving me that.
So the job was really three jobs: keep one folder in sync, keep a large archive safe and cheap, and make all of it reachable from a phone.
The cheapest option didn’t win
| Option | What it costs at my size | Notes |
|---|---|---|
| Dropbox Plus | $120 a year | 96.6% of the plan unused |
| Backblaze B2 | about $5 a year | Charges for downloads beyond a free allowance |
| Cloudflare R2 | about $10.50 a year | No download fees at all |
B2 was cheaper per gigabyte. R2 won for two reasons. It doesn’t charge for data going out, which makes streaming a video to my phone free, and it makes leaving free too. And the storage and the small program that sits in front of it live on one platform, so that program never needs a storage password.
I almost built a sync service
My first instinct was to write a sync service: a background program that watches folders and keeps the two machines and the cloud in step. I talked myself out of it the same day.
A well-established open-source tool, rclone, already does two-way sync. It resolves conflicts by keeping the newer file. It keeps a copy of anything deleted or overwritten. It recovers from dropped connections. And it refuses to run if a sync would delete more than a set number of files, which is the safety fuse that matters most.
I have a rule I apply to client work: name the first real user of a thing before building it, or don’t build it. Here I applied it to my own project. I could name gaps rclone doesn’t fill, such as syncing instantly rather than hourly, or giving different programs access to different folders. None of them hurt yet. So none of them got built.
What runs instead is a 53-line shell script, every hour, on two machines. In order, it:
- Empties a drop folder. Anything I put in it is uploaded to the archive and removed locally once it’s safely stored. That is the whole procedure for archiving something. There’s no app for it.
- Writes an index of everything in the archive, as one file. It only replaces the old index if the listing fully succeeded, so a half-finished run can never publish a half-finished index.
- Syncs the live folder both ways, keeping every deleted or overwritten file in a dated trash folder.
That last part matters more than it looks. R2 doesn’t keep old versions of files the way Dropbox does. Without the trash folders, a bad sync would mean lost work. With them, it means a folder to copy back from.
Before switching anything, I ran a full comparison between Dropbox and the new archive. It found zero differences.
Where the custom code went
The custom code went where no existing tool fits: the layer in front of the storage, and the phone.
I called it Bento, as a nod to Dropbox. It’s a small API, 325 lines of TypeScript, running on Cloudflare next to the storage. It holds no storage keys, because the platform connects it to the buckets directly. Every request to it needs a token, and every token carries a short list of rules: which bucket, which folder, read-only or read-write. The tokens themselves are never stored, only a fingerprint of each one. If I revoke a token on the server, the app on my phone notices the next time it asks for something, forgets it, and goes back to setup.
The app is one codebase that runs on my Mac and my iPhone. It loads the index once, so browsing and search are instant and cost nothing. Photos and video stream straight from storage, and you can scrub through a video. PDFs and Office files open in the phone’s own document viewer, so nothing is bundled. Archived web pages open with scripts and network access switched off, because old HTML isn’t something an app should trust. Face ID guards the phone.
The migration took three days of attention in early October. The API and the app took one more day, three weeks later.
What this means for a business
None of this is really about saving $110 a year. It’s about which parts you rent and which parts you control.
“Own your data” is the wrong phrase, strictly. Cloudflare holds the bytes, just as Dropbox did. And Dropbox would have let me download everything. What changed is everything around the bytes. The files are plain objects in a format every major storage provider speaks. The same rclone command that brought them in would move them somewhere else, and with no download fees, leaving costs nothing. The storage is a commodity I rent and could swap. The layer above it, meaning who can see what, the index, and the app, is mine. It’s the same idea as swapping the model under an AI agent: rent the part that’s interchangeable, and keep the part that’s specific to you.
Access is a rule you can read. I split the storage into two buckets, the live folder and the archive, because Cloudflare’s own access keys can be limited to a bucket but not to a folder inside one. So the bucket is the hard boundary. Anything given a key to the live folder cannot read the photo archive, no matter what it asks for. Inside that, Bento’s rules narrow access further, down to a folder, read-only or read-write.
In a business, that is the difference between hoping a sharing setting is right and knowing. A bookkeeper gets read-only access to one folder of invoices, and loses it when one line is deleted. A contractor sees the project they’re on, and not the one next to it. The rules are one short list you can read top to bottom, not a setting spread across a hundred shared folders.
It’s built so an agent can be let in carefully. This is the part I haven’t built, so I’ll be precise. The index is a single list of every file, which is what an AI agent would need to find things. The token rules are what it would need to be kept out of things. When I do put an agent on this, it will get its own token, for one bucket, read-only, and it won’t be able to see anything else. Every one of its requests goes through code I wrote and can read. That is a very different position from turning on an AI feature inside someone else’s app and trusting its settings.
Who shouldn’t do this
If several people edit the same documents together, share links with clients, or rely on Dropbox’s version history and comments, this is the wrong trade. Those are real features, and rebuilding them would cost far more than $120 a year. What I had was mostly an archive with one working folder, used by one person. That shape is common, but it isn’t universal.
Where it stands
It isn’t finished, and I’d rather say so.
- Dropbox is still running until the renewal date. The plan is a final catch-up copy and one more comparison the day before, then cancelling.
- The app is on my phone, not in any store. It’s for me. A clean standalone build is the next step.
- Deleting from the app is designed but not built.
- Camera uploads haven’t been sorted. Forty gigabytes, never culled. That is where the next real savings are, and no tool is going to do it for me.
If your business’s files live in someone else’s app and nobody can quite say who has access to what, that is a good question for a walkthrough to answer.