Note · Architecture

Shipping software with no backend at all

Half of what I build has no server behind it at all. Here's the pattern, why SMEs like it, and where it stops working.

Vanilla JS · IndexedDB · File System Access API ~6 min read

Half my portfolio has no server. Not "a small server", not "serverless" in the cloud-vendor sense, none. Just a file the user already owns, and an app that reads and writes it.

The pattern

The shape repeats across very different tools. Shipyard IMS treats the shipyard's own Excel workbook as the canonical data: the app reads it, edits it, writes it back, and the file on disk is the truth. The Retail Shift Scheduler keeps its working data in IndexedDB inside the browser, with export whenever the manager wants a copy outside the tab. A quiz platform I built syncs through a shared OneDrive folder, one file per attempt, so two people submitting at the same moment never collide, because they're never writing to the same file.

In every case the app itself is one artifact: one HTML file, or one .exe. There's no install step beyond putting the file somewhere, and no update process beyond replacing it with a newer one. Nothing runs that the user didn't start themselves, and nothing keeps running after they close the tab or the window.

Why SMEs actually like this

None of this is a purity test. It's what the businesses I work with actually need. There's nothing for an IT department to approve, because there's no server to stand up and no account to provision. There's no monthly hosting bill, SGD 0 a month, because there's no infrastructure sitting between the app and the file. And the data outlives the app: if I disappeared tomorrow, the Excel workbook and the OneDrive folder would still be exactly where they are, openable by anything that reads their format. A server-backed tool ties your data to my continued existence as a vendor. A file on disk doesn't.

Proof it holds up at real scale

The pattern isn't a toy-project trick. Shipyard IMS handles roughly 82,000 inventory allocations inside a browser tab, in production, at a working shipyard, with no database behind it. The Retail Shift Scheduler carries 135 combined tests, unit and end-to-end, and runs real rostering for a real store. The quiz platform is in ongoing daily use, syncing exclusively through that shared folder, with no server it has ever needed. These aren't demos I'm hoping will scale; they're the current, working state of each tool.

When it's the wrong call

The pattern has real edges, and I'd rather name them than pretend otherwise. Multi-user realtime editing, several people changing the same record at the same moment and expecting to see each other's changes live, doesn't fit a model where the file is the single source of truth. Data too large to comfortably hold in a browser tab or a local file stops being a zero-backend problem and starts being a database problem. And anything that needs a secret the client can't be trusted to hold, an API key, a credential, a rate limit that has to be enforced somewhere the user can't tamper with it, needs a server, because a browser or a plain .exe simply can't keep a secret.

This site's own chatbot is the worked example of that last case. It calls a language model that needs a bearer token, so that piece runs behind a thin Cloudflare Worker instead of client-side. That's the honest boundary: a Worker's entire job there is holding one secret and proxying one request. Everything else on the site, including the chat widget's UI, is still a static file with no server behind it. Reach for a backend when you actually need one, not by default.

Need an internal tool that runs without IT approval?

Let's talk about whether your problem needs a server at all.

Get in touch