Skip to main content
A microservice is a standalone unit that lives under modules/<kebab-name>/ and runs as its own process. Running ooneex microservice:create scaffolds the same definition-plus-config skeleton as a plain module, then adds the pieces a service needs to boot and deploy on its own: an entrypoint, an application start hook, its own environment config on a distinct port, role configuration, and a Dockerfile. Unlike a module, a microservice is not registered into AppModule or SharedModule — it runs independently and is wired to the rest of the system through networking config. This page walks through that layout file by file. See Overview for what a microservice is, Networking for how it is declared and reached, and Composition for how its internals combine. For the plain-module skeleton it builds on, see Module structure.

Layout

A freshly created billing microservice looks like this:
modules/billing/
├── billing.yml                    # module config (type: "microservice")
├── .env.yml                       # service environment (its own app.port)
├── roles.yml                      # role configuration for the service
├── Dockerfile                     # build and deploy the service independently
├── package.json                   # workspace package: @module/billing
├── tsconfig.json                  # TypeScript config
├── src/
│   ├── BillingModule.ts           # module definition (ModuleType)
│   ├── index.ts                   # microservice entrypoint
│   ├── OnAppStart.ts              # application start hook (runs on boot)
│   ├── controllers/               # @decorator.controller() classes
│   ├── services/                  # injectable services
│   ├── repositories/              # data-access repositories
│   ├── entities/                  # database entities
│   └── middlewares/               # IMiddleware / ISocketMiddleware classes
└── tests/
    └── BillingModule.spec.ts      # asserts the ModuleType arrays exist
The artifact subfolders under src/ (controllers/, services/, repositories/, entities/, middlewares/) are created on demand as you generate artifacts into the service — a new microservice starts with just src/BillingModule.ts, src/index.ts, and src/OnAppStart.ts.

Generated files

Every file below is written by microservice:create. The first group mirrors a plain module; the rest are unique to microservices because they run as their own process.
FilePurpose
src/<Pascal>Module.tsThe module definition. Exports a ModuleType whose arrays declare the service’s artifacts.
src/index.tsThe microservice entrypoint — the same template as the app entrypoint, pointed at <Pascal>Module instead of AppModule.
src/OnAppStart.tsAn application start hook that runs when the microservice boots.
<kebab-name>.ymlModule config with type: "microservice".
.env.ymlThe service’s own environment config: a distinct app.port, cache / pubsub / rate_limit Redis URLs, and a Postgres database.url.
roles.ymlThe role configuration for the service.
DockerfileLets the service be built and deployed independently.
package.jsonWorkspace package named @module/<kebab-name> with test and lint scripts.
tsconfig.jsonTypeScript config.
tests/<Pascal>Module.spec.tsMirrored test asserting each ModuleType array exists.

src/<Pascal>Module.ts — the module definition

The heart of the service. It exports a single ModuleType object whose arrays declare what the service contributes. You register each artifact you create by adding it to the matching array.
import type { ModuleType } from "@ooneex/module";

export const BillingModule: ModuleType = {
  controllers: [],
  entities: [],
  middlewares: [],
  cronJobs: [],
  events: [],
};

<kebab-name>.yml — module config

The config file marks the unit as a microservice. The type field distinguishes it from the other kinds of unit (api, microservice, design, spa, sdk, module); for a microservice it is set to microservice.
type: "microservice"

Files unique to a microservice

A plain module stops at the definition, config, package, tsconfig, and test. A microservice adds the files it needs to run and ship on its own:
FileWhy a microservice needs it
src/index.tsA module is mounted inside the app; a microservice is its own process, so it needs an entrypoint to start.
src/OnAppStart.tsA boot hook to run setup when the service starts standalone.
.env.ymlThe service runs on its own port and connections, so it carries its own environment rather than sharing the app’s.
roles.ymlRole configuration scoped to the service.
DockerfileThe service is built and deployed independently of the API.

src/index.ts and src/OnAppStart.ts

src/index.ts is the entrypoint that boots the service. It is the same template as the app entrypoint, but it loads <Pascal>Module instead of AppModule. src/OnAppStart.ts is the start hook the entrypoint invokes — application setup that should run once when the microservice boots.

.env.yml — its own port

Because a microservice is a separate process, it gets its own environment config with a distinct app.port. Port 3000 belongs to the API; microservices start at 3001 and each new service picks the next free port. The file also carries the service’s cache, pubsub, and rate-limit Redis URLs and its Postgres database.url.

Not registered in AppModule

A microservice is not added to AppModule or SharedModule — it runs standalone rather than being mounted into the main app. Instead it is declared for networking in modules/app/app.yml and the root .env.yml, which is how other services discover and reach it. See Networking for that wiring, and Deployment for building and shipping the service from its Dockerfile.