What is Base, and why we built it
The one object that is your worker, and why a framework should hand you the pieces already fitted.
What is Base, and why we built it
Most backend frameworks ask you to make a hundred small decisions before you write a line of business logic. Which router. Which validation library. Which ORM, which GraphQL server, which way to wire them together so they share types. Each choice is reasonable on its own. Together they become a stack you assemble, maintain, and explain to every new engineer who joins.
Base starts from a different premise: the framework should hand you those pieces already fitted together, so the only decisions left are the ones about your product.
Base is a modular framework for building applications on Cloudflare Workers. It gives you dependency injection, modules, an HTTP router, RPC, GraphQL, an ORM, validation, serialization, queues, scheduled workers, websockets, KV, object storage, Durable Objects, and an event bus. One framework, one set of conventions, one place to look when something breaks.
The whole shape, in two pieces
Here is a Base worker. Not a snippet with the boring parts removed. The whole entry point:
That is the entire bootstrap. BaseWorker.create takes one settings object and returns a worker Cloudflare can run. Everything your application does is described in that settings object and in the classes it points to.
The settings object is the map of your worker. You declare what your worker has, and Base wires it:
Notice the orm block. You name your database driver and entities, and Base brings a Drizzle-backed ORM already fitted to it. That is the pattern throughout: the framework hands you a good default for the edge, like Drizzle over PlanetScale or Cloudflare D1, so you are not choosing and wiring a data layer from scratch. You can still reach for what you need, but you start from working, not from a blank file.
The second piece is the class. A route, a resolver, an RPC procedure, an entity. You write a plain TypeScript class and decorate it to say what it is. Base reads the decorators, registers the class, and injects what it needs. You do not register routes by hand, thread a database connection through every function, or keep a wiring file in sync with reality.
So the mental model for all of Base is two moves: add a key to the settings object, write one decorated class. The thesis article you are reading is the only one that talks about Base in the abstract. Every other post is a variation on those two moves.
Add only what you need
A common worry about an all-in-one framework is weight. If it ships a router and a GraphQL server and a queue system, am I paying for all of it on every worker?
No. In Base, only three fields are required: name, title, and version. Everything else is optional. A worker that only serves HTTP declares a router and nothing else. A worker that only processes a queue declares a queue. A worker that does both declares both. You are not turning features off; you are only ever turning the ones you use on.
This is what we mean when we say Base does not prescribe an architecture. It does not push you toward a monolith or toward many small services. The same framework builds one worker that does everything and a fleet of workers that each do one thing, because the unit is always the same: a settings object plus the classes it names. Compose them however your product wants to be shaped.
Loosely coupled, by construction
The pieces fit together, but they are not fused. Base leans on dependency injection so your classes ask for what they need and receive it, rather than reaching out to grab globals. A service that needs the database declares it as a dependency. Base provides it. In a test, you provide a different one. Nothing in your business logic knows or cares where the real connection came from.
That looseness is why the same decorated class can be reached over HTTP, over RPC, and from a GraphQL resolver without rewriting it. The transport is wiring; your logic is the class. The framework's job is to keep those two things separate so each can change without dragging the other along.
Built for the edge, built to last
Base targets Cloudflare Workers because the edge is where we want our applications to live: close to users, scaled by the platform, billed for what runs. The ORM ships adapters for the databases that belong there, including Cloudflare D1 for SQLite at the edge and PlanetScale for MySQL.
Enterprise-ready is not a feature you add later. It is the validation that runs before a request reaches your handler, the serialization contract that keeps your API stable, the typed boundaries between workers, and the testing story that lets you trust a deploy. Base treats those as part of the foundation, not as plugins you bolt on once the product is real.
Why we built it
We were assembling the same stack on every project, then maintaining the seams between the parts forever. The integration work was never the interesting work, and it was never finished. Base is the framework we wanted to already have: the pieces chosen, fitted, and typed end to end, so the time goes into the product instead of the plumbing.
The name says the rest. It is the base you build on, so you can spend your attention higher up.