<PascalName>Module of type ModuleType from @talosjs/module that declares what the service owns. You list artifact classes in the appropriate array, and the framework resolves and wires each one through the dependency injection container. Controllers join the router, middleware joins the pipeline, cron jobs join the scheduler, events join the bus, and entities join the data source.
The one thing that sets a microservice apart is exposure. A plain module is registered into AppModule/SharedModule so the app process can resolve it. A microservice is not. It runs as its own process, with its own DI container, its own port, and its own Dockerfile, and its src/index.ts entrypoint boots the service directly from its own module. Composition is identical; what changes is who runs it.
How it works
The service’sModuleType has one array per artifact kind. Listing a class is the declaration. Within the microservice’s process the framework reads the module, registers each class with the container, and applies its decorators.
Every class you list is resolved through the microservice’s DI container. That is what makes a bare array entry enough: the container constructs the class, injects its dependencies, and the framework reads its decorators to plug it into routing, the scheduler, or the event bus. It is the same resolution model as any Talos app, just running in a process of its own.
Composing the service module
Build the module up one array at a time. Each array maps to a kind of artifact the service owns, nothing more. A completeBillingModule for a self-contained billing service looks like this.
controllers
Both HTTP and WebSocket controllers go incontrollers. The service registers each one’s routes from its @Route.* decorators.
entities
List the TypeORM entities the service persists. A microservice owns its own database, so these entities back its own data source, not a shared one.middlewares
Middleware that intercepts the service’s requests or socket connections goes here, registered via its@decorator.middleware().
cronJobs
Scheduled work the service runs on a timer belongs incronJobs. Each job is registered with the scheduler from its cron expression, and runs inside this service’s process.
events
Pub/sub handlers the service reacts to (or emits) go inevents. Each is registered as a subscriber on the event bus.
Booting from the service’s own module
This is where a microservice diverges from a plain module. A module declares its artifacts and is then registered into a destination module so the app process can resolve them; see module composition, whereOrderModule is spread into AppModule.
A microservice skips that step entirely. It is never registered into AppModule or SharedModule. Instead, the template wires the microservice’s src/index.ts entrypoint to boot the service from its own module, so the service’s process resolves BillingModule directly.
src/OnAppStart.ts runs so the service can perform any setup it needs (connecting to its data source, warming caches) before it begins handling traffic. From there, resolution flows through the microservice’s DI container exactly as it would in any Talos app: every class listed in BillingModule is registered with the container, and the framework applies the decorators. Controllers join the router (see routing), middleware joins the pipeline, cron jobs join the scheduler, events join the bus, and entities join the data source.
Keeping the service isolated
A microservice is a vertical slice that owns a single domain end to end. Keep billing inBillingModule; if a concern belongs to another domain, it belongs to that domain’s service. Declare the service’s own entities and let it own its database. A microservice should never reach into another service’s data source or share tables.
When the billing service needs data from another service, call it over the network (see networking) rather than importing that service’s controllers, entities, or repositories. Every array entry is a declaration of ownership, and resolution happens inside this process, so list only the classes this service actually runs.
Two habits keep the isolated-process model intact. A microservice boots from its own module, so don’t wire it into AppModule. And lean on the generators: scaffolding with the :create commands (controller:create, service:create, entity:create, and so on) targets the microservice’s module and writes into its src/, which keeps the module in sync without manual edits.
Learn more
- Microservice overview: what a microservice is and how it differs from a module.
- Microservice structure: how the service’s files, entrypoint, and
.env.ymlare laid out on disk. - Microservice networking: calling other services over the network instead of importing them.
- Module composition: composing a module that is registered into
AppModulerather than booted on its own. - Dependency injection: how the container resolves and wires declared artifacts.
- Routing: how
@Route.*decorators turn controllers into routes.