Skip to content

Runtime and services

Workers at the edge

JavaScript that runs in Cloudflare's network rather than on a server we keep alive; it hosts most of the APIs we ship.

A Worker is a small JavaScript or TypeScript program that runs inside Cloudflare's network, started when a request arrives and discarded afterwards. There is no machine to keep alive, no container image, no operating system to patch. You deploy a bundle plus a set of bindings, which are the handles the code gets on a database, a bucket, a queue or a cache, and billing is per request and per millisecond of processor time actually used rather than per hour of something sitting idle.

How we use it

It is the default runtime for our own products, so most of the portfolio runs on it. Objectify is one Worker in front of ten SQLite databases, resolving an API key to a tenant to a shard on every request. DMARC Engine runs its Next.js application on Workers through OpenNext and puts the awkward jobs in Workers of their own: report ingest, which parses MIME, unzips attachments and verifies the reporting sender, and a scheduled worker that flattens SPF records and republishes them. atHeartbeat serves its whole API from a single Worker on api.atheartbeat.com, and ClassProfile does the same with a separately hosted front end talking to it. Jonosakti is another Next.js application on Workers via OpenNext.

Two builds belong in a different sentence. Taxcare Accountancy and AHZ Associates have Cloudflare in front of them, setting the content security policy, HSTS and frame options at the edge, but the applications themselves run elsewhere. Sitting behind the edge is not the same as running on it, and we would rather say so than count them twice.

What it costs you

Processor time per request is capped, and it is a much smaller budget than wall clock time. Waiting on a database or an API is nearly free; encoding an image or parsing a large XML document is not. The report ingest in DMARC Engine unzips and parses attachments in a Worker, and that sizing has to be checked against the biggest real report you expect rather than the one in the test fixture.

Nothing survives between requests. There is no in-process cache you can trust, no background thread, no warm connection pool. Work that happens after the response goes to a queue or a deferred task, which is more moving parts than a setTimeout on a server.

Node compatibility is partial and always will be. Anything reaching for the file system, raw sockets or a native addon will not run, which rules out a large slice of npm including most conventional database drivers. Local development is a good emulator rather than the platform, and bindings such as Images, Stream and Browser Rendering only really exist in production with secrets set, which is how you end up with an endpoint that works everywhere except where it matters.

The bindings are also the lock-in. The application code is ordinary TypeScript and would move tomorrow. The database, the object store, the queue, the key-value namespace and the coordination objects would each have to be replaced separately, and there is no afternoon during which that is a small job.

When we would choose something else

If the work needs a process that stays up, holds connections and runs for minutes, we would put NestJS on a normal host and accept the hourly bill for it, because fighting the runtime is more expensive than paying for a server. We put figures on both sides of that in what a Postgres, Redis, broker and search stack costs at rest. Where the people maintaining the thing after us write PHP, Laravel is the better answer regardless of what the architecture diagram prefers. And where an application is genuinely a set of pages with a form on it, static hosting with no runtime at all beats every option here.

Where we have used it

Every build below lists this in its stack, so the claim is checkable.