Module map
A bird's-eye view of every module in the Titan ecosystem — who depends on whom, who can substitute for whom, and which combinations show up in real backends.
Dependency graph
Solid arrows are hard dependencies — you can't run the
dependent module without the foundation. Dotted arrows are
soft / optional — feature flagged at config time
(storage: 'redis', multiTier: true, enableDatabaseIndicator: true).
Install footprint
The numbers below count peer modules a typical adoption pulls in (transitive Redis client, postgres driver, etc. are omitted):
| You install | What else lights up |
|---|---|
titan-events | Standalone |
titan-redis | Standalone |
titan-database | Standalone (+ db driver) |
titan-cache | Standalone (+ titan-redis if multiTier: true) |
titan-lock | + titan-redis |
titan-discovery | + titan-redis |
titan-ratelimit | Standalone (+ titan-redis if storage: 'redis') |
titan-notifications | + titan-redis (+ titan-database for preference store) |
titan-scheduler | Standalone (+ titan-redis for distributed persistence) |
titan-auth | Standalone (+ titan-cache for token cache) |
titan-health | Standalone (indicators light up per enableXxxIndicator) |
titan-metrics | Standalone (+ storage driver if persisting) |
titan-telemetry-relay | Standalone (paired with titan-metrics at remote end) |
titan-pm | Standalone |
The framework deliberately keeps modules independently versionable — you only pull in what you actually use.
Common stacks
Web API service
@omnitron-dev/titanconfig + loggerShips inside @omnitron-dev/titan. No additional install required.
titan-redis + titan-database + titan-cache + titan-auth + titan-health + titan-metricsMaintained by the Omnitron team. Independent npm package.
Common starting set for any REST / RPC backend.
Worker fleet
@omnitron-dev/titanconfig + loggerShips inside @omnitron-dev/titan. No additional install required.
titan-redis + titan-database + titan-lock + titan-scheduler + titan-metrics + titan-healthMaintained by the Omnitron team. Independent npm package.
titan-lock is what stops two workers running the same job.
Notification gateway
@omnitron-dev/titanconfig + loggerShips inside @omnitron-dev/titan. No additional install required.
titan-redis + titan-notifications + titan-ratelimit + titan-metricsMaintained by the Omnitron team. Independent npm package.
titan-ratelimit shields the upstream provider; titan-metrics
records throughput / failures by channel.
Multi-instance app
Add titan-discovery to any of the above when you have more
than one pod and want to address services without hard-coded URLs.
Edge / offline node
titan-telemetry-relayMaintained by the Omnitron team. Independent npm package.
Add titan-telemetry-relay when the node may be disconnected from
the central metrics endpoint — it buffers samples to SQLite and
flushes when connectivity returns.
Similar modules — when which?
| Need | Reach for | Why |
|---|---|---|
| Sync in-process pub/sub | titan-events | Fire-and-forget, intra-process, typed channels |
| Reliable cross-pod queue | titan-notifications | Built on rotif; survives crashes, has DLQ + retry |
| Periodic work (cron / interval) | titan-scheduler | Per-job persistence + missed-fire handling |
| Memoize a function call | titan-cache | @Cached(...) decorator; multi-tier (L1+L2) |
| Talk to Redis directly | titan-redis | Just a typed client; no service abstraction |
| Throttle calls | titan-ratelimit | Token-bucket / sliding-window / fixed-window |
| Coordinate across instances | titan-lock | Redis-backed mutex with UUID ownership |
| Spawn / supervise child processes | titan-pm | Worker pools, IPC, crash supervision |
| Find sibling services | titan-discovery | Heartbeat-based service registry |
| Count / measure | titan-metrics | Counters, gauges, histograms; Prom exposition |
| Ship metrics off-host | titan-telemetry-relay | Store-and-forward; survives offline windows |
| Check it's alive | titan-health | k8s probes + custom indicators |
| Authenticate RPC callers | titan-auth | JWT (HS256/RS256/ES256), JWKS, token cache |
| Query a database | titan-database | Kysely + migrations + RLS |
| Validated config | config (built-in) | Layered, validated, hot-reloadable |
| Structured logging | logger (built-in) | pino under the hood; transports + processors |
Replacement / overlap matrix
| Module | Closest overlap | When to prefer |
|---|---|---|
titan-events | titan-notifications | In-process / no persistence / lowest latency |
titan-notifications | titan-events + titan-scheduler | Cross-process, retry, DLQ, channel templating |
titan-cache | bare titan-redis | Caching semantics (@Cached, TTL, multi-tier) |
titan-scheduler | setInterval / node-cron | Persistence, missed-fire, observability |
titan-lock | bare SETNX on Redis | Safe ownership (UUID) + Lua-script atomicity |
titan-discovery | env-var URL config | Dynamic topology, autoscaling, rolling deploys |
titan-metrics | prom-client | Native persistence + cross-pod aggregation |
titan-telemetry-relay | direct Prom scrape | Edge / offline / store-and-forward |
titan-health | rolling-your-own /healthz | Standard k8s probe shapes + indicator registry |
titan-auth | manual JWT verification | JWKS rotation, token cache, RBAC primitives |
Where Redis sits
Five official modules use Redis as their primary backend. They
share the same Redis client provided by titan-redis:
Register TitanRedisModule.forRoot(...) once at app boot; all
five pick up the connection automatically.
@Module({
imports: [
TitanRedisModule.forRoot({ config: { url: env.REDIS_URL } }),
TitanLockModule.forRoot(),
DiscoveryModule.forRoot(),
TitanCacheModule.forRoot({ multiTier: true, l2: { /* picked up */ } }),
TitanRateLimitModule.forRoot({ storageType: 'redis' }),
NotificationsModule.forRoot({ /* … */ }),
],
})
class AppModule {}
Recommended Redis-DB split (avoid keyspace collisions):
| DB | Purpose |
|---|---|
| 0 | App data (cache, sessions, business state) |
| 1 | Queues / pub-sub (notifications, events) |
| 2 | Rate limits |
| 3 | Locks (titan-lock) |
| 4 | Discovery registry |
Configure per-module by passing a different db: index in the
options, or by registering multiple named Redis clients via
TitanRedisModule.forRootMultiple([...]).
Lifecycle order — first to last
The container resolves lifecycle in dependency order:
On shutdown, the reverse order is followed — user services drain first, then surface modules, then foundations, then logger / config last. The exact reverse ensures dependants always stop before their dependencies.
Picking the right tier
| Question | Tier |
|---|---|
| Always available, smallest install? | Built-in |
| Battle-tested, official, individually versioned? | Official |
| Niche need, no official equivalent yet? | Community (audit first) |
| Want to publish your own? | Authoring a module |
See also
- Modules index — flat list by tier
- Authoring a module — conventions every official module follows
- Recipes — concrete combinations that solve real problems