Anatomy of a Microservice
microservice/create-microservice.ts is the facade every Primebrick
service boots through. It sequences ~12 wired stages — env, DAL, config,
auth, NATS, shield, HTTP, registration, health, shutdown — so a service is
declared by its options, not by handwritten infrastructure.
Boot sequence
Code
The MicroserviceContext returned exposes env, configLoader,
natsClient, registrar, healthCheck — the handles onReady uses to
wire the service's own logic.
Topology — where a service sits
A microservice never answers public HTTP. Its HTTP surface exists only to be called by the BE proxy (or by other services over internal fetch); its outbound face is the NATS fabric.
Two authentication layers — L1 and L2
Every inbound call clears two distinct walls:
| Layer | Question | Mechanism | Details |
|---|---|---|---|
| L1 — client/network | Is the caller a trusted client? | x-client-shield-secret (rotating) + client-identity gate (User-Agent vs client-registry) | client-shield-and-secrets |
| L2 — user/RBAC | May this user do this? | resolved AuthUser → permissions[] on the RpcRoute, defaultDeny | authentication, rpc-router |
The same split applies on NATS: verifyNatsPublisher + subscribeShielded
(L1) before any subject handler runs.
The NATS fabric
| Subject family | Direction | Purpose |
|---|---|---|
service.register / service.unregister / service.heartbeat | US → BE | lifecycle announcements the registry consumes |
service.gateway_online | BE → all | "the gateway is back" — triggers re-registration and re-pulls |
config.get | US → BE | governed config lookups |
secret.get | US → BE | correlation-route request for the shield slot (allowlisted) |
secret.rotated | BE → all | shield rotation broadcast — consumers refresh their slot |
client_shield_registry.get | US → BE | known-client lookups for the identity gate |
webhook.<code>.received | webhook US → target US | JetStream stream for durable webhook delivery |
Pub/sub is the default; JetStream only where durability/replay matters.
NATS request/reply is deprecated — governed correlation routes
(makeNatsRequestRoute) replaced it.
What the service must declare
Required: serviceName, envSchema, initDal, dalClose,
configRepositoryAdapter, authConfigPort, healthCheckPort.
Optional: routeHandler (factory-produced only — makeRpcRouter,
makeOpenApiHandler, composeRouteHandlers; arbitrary handlers are
rejected), apiKeyPort, endpoints, customHealthChecks,
identityExemptPaths, docsPackDir, authDependencySetters, onReady,
identity/display/icon fields for the registry.
Deep-dives
- Boot options & context → this page +
service-registration.mdx - HTTP routes & middleware chain →
rpc-router.mdx,http-server.mdx - Entity CRUD factory →
entity-router.mdx - Spec from routes →
openapi-generation.mdx - Docs to the KB →
docs-pack.mdx - Secrets & shield →
client-shield-and-secrets.mdx - NATS client →
nats-client.mdx; SSE →sse-standard.mdx