Base modules: what, why, and how

The composition unit: a self-contained slice that brings its own services and settings to a worker.

Foundations
AhraJuly 22, 2026

Base modules: what, why, and how

A worker's settings object describes one worker. But a lot of what a worker does is not unique to it. Authentication, a billing surface, a notifications system: these are coherent bundles of routes, entities, listeners, and configuration that you would want to drop into more than one worker without copying and pasting. A Base module is that bundle, packaged so a worker can adopt it by naming it.

What a module is

A module is a reusable unit of a worker's capability. Where a worker has settings (a router, an ORM connection, GraphQL resolvers, event listeners, scheduled work), a module can carry its own slice of those same things. You create one by giving it a name and its settings, and the worker that uses it gets everything the module declares, wired in as if the worker had declared it itself.

Think of it as a worker's worth of a feature, minus the worker. The module says "here are my routes, my entities, my listeners," and any worker can pull that whole feature in by listing the module.

Why modules exist

Two reasons, and they are the usual two: reuse and boundaries.

Reuse is the obvious one. A feature built as a module can be used by every worker that needs it, defined once. You fix a bug in the module's logic, and every worker that adopted it gets the fix. You are not maintaining four slightly diverged copies of your auth code.

Boundaries are the quieter, more important one. A module draws a line around a feature. Everything that feature needs lives inside the module: its routes, its data, its configuration. The worker that uses it does not have to understand the feature's internals; it just adopts it. That keeps a growing application from collapsing into one undifferentiated settings object where everything knows about everything. Modules are how a Base application stays legible as it grows.

How you use one

A module is created with a name and its settings, and a worker adopts it by listing it in the modules key of its own settings. From the worker's point of view, that one line brings in the whole feature. The module's routes become the worker's routes, its entities become part of the worker's data layer, its listeners start hearing events. The worker composes features by listing modules, the same way it composes capabilities by setting keys.

Modules can also build on each other. A module can declare that it uses other modules, so a higher-level feature can be assembled from smaller ones. And a module can hook into its own lifecycle, doing setup when it is created or initialized. The shape is recursive in the good way: a module is a composable unit, and you compose them into a worker, or into bigger modules, with the same move.

The mental model to keep

A module is a feature packaged as a reusable bundle of settings: routes, data, listeners, configuration, drawn together behind a name. Workers adopt modules by listing them, modules can use other modules, and each module is a boundary that keeps a feature's internals to itself. It is the same composition idea as the rest of Base, scaled up from "add a key" to "add a feature."

Base modules: what, why, and how • System