professional headshot photo of Mr Palumbo

One Framework, Thirty Apps: What "Infinite Scale" Really Means on Cloudflare Workers

I run a fleet of around thirty web apps by myself, and they all share one architecture: a static Next.js frontend on Cloudflare Pages, a Cloudflare Worker for the API, and a D1 database. New projects are cloned from a single template repo, and shared packages handle auth and email so I never write a login flow twice.

I catch myself telling people this setup "scales infinitely." This post is me checking that claim against the actual architecture. The short version: the efficiency story is real and better than most people expect, and the infinite story is true for exactly half the stack. Knowing which half is the whole game.

~30
apps on the framework
29
D1 databases
2
deploys per app
$0
cost while idle
01 · The shape

Two deployments, joined by a fetch

Each app is two separate deployments. The frontend is a Next.js project built with output: 'export', which means every route becomes a plain HTML file at build time. There is no server rendering, no middleware, no API routes - just files, served from Cloudflare's CDN. The backend is a Worker: a small router that speaks JSON under /api/v1, talks to D1, and sends email. The two are joined by nothing but a cross-origin fetch guarded by CORS.

The fleet architecture Browser Cloudflare Pages static HTML from Next.js export Worker API router /api/v1 D1 (SQLite) one primary per database Email provider GET pages fetch + CORS
The whole stack. Static files never touch the Worker; the Worker never serves HTML. Each side scales - and fails - independently.

The framework is a template repo, not a package. A new app is a clone plus a config file, a D1 database id, and two secrets. Shared @latentfreedom packages carry the parts that must not drift: password hashing, JWT sessions, email templates, CORS, and error envelopes.

02 · The efficiency

Why Workers are cheap to run and cheap to think about

The usual mental model for a backend is a server: a container or VM that boots in seconds, sits warm costing money while idle, and needs patching. Workers do not work that way. A Worker is a V8 isolate - the same lightweight sandbox Chrome uses for browser tabs - spun up inside a process that is already running on thousands of machines. Cold starts are single-digit milliseconds, not seconds, and an idle Worker costs nothing at all.

  • Scale to zero, for real. A fleet of thirty apps where twenty-five get light traffic would be financial nonsense on containers. On Workers, an app that gets no requests generates no bill. That is the property that makes a solo fleet viable at all.
  • Scale up is not my problem. There is no instance count, no autoscaler config, no load balancer. A traffic spike lands on Cloudflare's scheduler, not on a pager.
  • Nothing to patch. No OS, no base image, no node version rotting on a forgotten VPS. The runtime is Cloudflare's job.
  • The static half is even cheaper. Pre-rendered HTML on a CDN is the most scalable artifact in computing. The frontend of every app in my fleet could take an arbitrary traffic spike and the only observable effect would be a bandwidth graph.
The real efficiency metric The cost that matters for a fleet is not dollars per request - it is marginal effort per additional app. Here that is close to zero: clone the template, create a database, deploy twice. The thirty-first app costs the same as the third did.
03 · The infinite half

What genuinely scales without limit

Three parts of this architecture really do have no practical ceiling for a fleet like mine:

  • Static reads. Every page load is a CDN file. Effectively unbounded.
  • Stateless auth checks. Sessions are JWTs, so verifying a request is pure cryptography inside the Worker - no database read required to know who is calling. Auth verification scales exactly as far as the Workers platform does.
  • The compute tier. The Worker itself is horizontally scaled by Cloudflare across its whole edge. More requests means more isolates; my configuration does not change.

Notice the pattern: everything that scales without limit is stateless. That is not an accident of Cloudflare's design. It is the oldest rule in distributed systems - state is the hard part - and this stack simply pushes all of it into one place.

04 · The finite half

Where "infinite" quietly stops being true

All of that state lands on D1, and D1 is SQLite: a brilliant, boring, single-writer database. Cloudflare has added global read replication, but every write to a database still goes through one primary, and each database has a 10 GB cap. So the honest sentence is: my reads scale like a CDN; my writes scale like one very well-run SQLite file per app.

And in my current setup there are three self-inflicted multipliers on that constraint, all of which I can name because I went looking:

  • Five apps share one database. By deliberate policy, a group of my dashboard apps use a single D1 with table prefixes instead of five separate databases. It keeps admin simple, but it means five apps' writes serialize through one primary and share one set of per-database limits. Worker scale-out does not help with that; it makes contention arrive faster.
  • There is no cache tier yet. No KV, no Cache API headers on GET responses. Every authenticated page load does a fresh database round trip to load the user. At my traffic this is invisible; at 100x it would be the first fire.
  • Compute runs at the edge, state lives in one place. Workers execute at whichever of Cloudflare's locations is nearest the user, while each D1 primary lives in one region. Smart Placement - the setting that moves the Worker next to the database it talks to - is still commented out across my fleet. Edge compute chatting with distant state is the worst latency shape, and I have the fix turned off.

There is also a scaling limit that has nothing to do with traffic: the template is copied, not depended on. Thirty apps each hold their own snapshot of the worker skeleton, and improvements propagate by an agent running a sync script, not by bumping a version number. That scales operationally only because automation does the walking.

LayerScales byPractical ceiling
Static frontend (Pages)CDNnone that matters
Worker computeisolates across the edgenone that matters
Auth verificationstateless cryptonone that matters
D1 readsread replicationhigh, and growing
D1 writesone primary per databasereal, and shared by co-tenant apps
05 · The verdict

The claim I am allowed to make

"Scales infinitely" is marketing. What this architecture actually does is subtler and, honestly, better: it scales to zero perfectly, which is what a thirty-app solo fleet needs every single day, and it scales up much further than any app I run is likely to demand - with a known, boring escape hatch at every layer when one of them outgrows it. Split the shared database. Turn on Smart Placement. Put KV or cache headers in front of hot reads. Each is an afternoon of work I get to defer until an app has earned the traffic that requires it.

The takeaway The infinite half of the stack is everything stateless, and Cloudflare genuinely handles it for me. The finite half is one SQLite primary per database - a ceiling I share with five of my own apps by choice. That is not infinite scale. It is something more useful: near-zero marginal cost per app, and a short, written list of exactly what to change the day a ceiling gets close.

Sources