Connectum Runtime Architecture
Connectum is a modular service runtime, not a deployment platform. Its central composition boundary is createServer(): it registers routes, protocols, and interceptors; selects the network transport; and coordinates startup, drain, and shutdown for one service process.
This page explains the runtime relationships that matter when extending or operating that process. Exact configuration fields remain in the generated core API, while deployment products and platforms remain in their focused guides.
Boundary and ownership
The framework owns the behavior inside a Connectum service process:
- transport selection and server lifecycle;
- registration of typed services and protocol plugins;
- the ordered server-interceptor chain;
- the
Contextsupplied to typed handlers; - local or remote service-call dispatch when a catalog is configured;
- lifecycle integration for an explicitly supplied EventBus.
Connectum does not own a gateway, service mesh, scheduler, message broker, or telemetry backend. Those systems connect through documented seams and can be selected independently.
Runtime composition
Every inbound network request follows one shared execution path. TransportManager owns the selected Node transport, buildRoutes() composes services and protocol registrations, the configured server interceptors run in order, and the matched route invokes a typed handler with a Connectum Context.
Protocol modules such as Health Check and Reflection register additional routes through the same router contract. EventBus and OpenTelemetry are opt-in capabilities: the server coordinates the supplied EventBus lifecycle, while OTel instrumentation attaches through server/client interceptors and its provider.
Network and in-process parity
An in-process client does not open a socket. createLocalTransport() calls createRouterTransport(routes) and supplies the same serverInterceptors before reaching the handler. Client-side interceptors may additionally wrap the in-memory call.
This shared route and interceptor boundary is the parity invariant: application behavior should not depend on whether a locally mounted service was reached over HTTP or through the in-process transport. See In-Process Transport for the exact guarantee, limitations, and test utilities.
Catalog call routing
Handlers use the generated service catalog through ctx.call and ctx.stream. The per-server catalog dispatcher resolves the typed method and builds the outgoing call frame from the current handler context.
Routing then depends on where the target service is mounted:
- A locally mounted
typeNameuses the in-process transport and re-enters the same process'sroutes, server interceptors, and typed handler chain. OnecreateServer()instance may register several servicetypeNamevalues. - A service not mounted locally is passed to
remoteResolver, which supplies the ConnectRPCTransportused for the remote call. The request then crosses the process boundary and enters the remote server through its resolver-suppliedTransportandconnectNodeAdapter({ routes, interceptors }).
The incoming cancellation signal and remaining deadline cascade to catalog calls unless the caller supplies a stricter override. Inbound headers are not forwarded implicitly; only configured allow-listed headers and explicit call headers are propagated.
CatalogDispatcher selects the transport; it does not select a different handler contract. Both the in-process createRouterTransport() path and the remote connectNodeAdapter() path apply the target server's routes and server interceptors before the handler. Stacked cards represent additional registered service typeName values; response arrows are omitted for legibility. The catalog is optional. A service process that hosts everything locally and makes no typed cross-service calls does not need one. Configuration and error semantics are owned by the Service Catalog guide, with resolver construction covered by Remote Resolvers.
Extension seams
| Capability | Runtime attachment | External dependency |
|---|---|---|
| Server interceptors | Ordered ConnectRPC request chain | Optional identity, policy, or application services |
| Protocol plugins | Register RPC routes and optional HTTP fallbacks | Protocol-specific clients and tooling |
| Service catalog | Adds typed ctx.call / ctx.stream dispatch | Resolver-supplied remote transports |
| EventBus | Supplied to createServer() and started/stopped with it | None for Memory; NATS, Kafka, Redis, or AMQP broker otherwise |
| OpenTelemetry | Server/client interceptors plus provider | OTLP collector or console exporter |
These are explicit capabilities rather than hidden runtime defaults. Install and compose only the modules required by the service.
Deployment boundary
Gateways, service meshes, Kubernetes, registries, and telemetry backends surround the process but are not framework prerequisites. Their placement depends on the deployment topology rather than on createServer() internals:
- Docker packages the process;
- Kubernetes schedules it and drives probes;
- Envoy Gateway provides an optional edge and REST transcoding path;
- Service Mesh provides optional traffic policy and workload mTLS;
- Observability selects telemetry signals and backends.
Build-time inputs
Proto schemas, generated service descriptors, and the optional generated service catalog are build-time inputs to this runtime. They are deliberately outside the process diagrams: they define and generate the contracts consumed by route and catalog registration, but they do not execute in the request path.
Start with Scaffolding for generation workflow and Service Communication for choosing between synchronous catalog calls and asynchronous events.
Related
- Server — composition and lifecycle entry point
- Transport Matrix — HTTP/1.1, h2c, TLS/ALPN, and RPC-kind support
- Choosing a Communication Mechanism — synchronous calls, events, and durable workflows
- Package decomposition ADR — package-boundary rationale