Configuration system
One typedConfigType per environment. process.env is read exactly once, in the matching configuration module — nowhere else in the codebase.
How it works
Docker Compose injects.env.development at the container boundary. The backend reads NODE_ENV, loads the matching configuration module, and assembles a single ConfigType object that’s passed everywhere.
Configuration modules
| File | When loaded |
|---|---|
apps/backend/src/configuration/development.ts | Local Docker dev (NODE_ENV=development) |
apps/backend/src/configuration/staging.ts | Railway staging environment |
apps/backend/src/configuration/production.ts | Railway production environment |
apps/backend/src/configuration/test.ts | Jest test suite (NODE_ENV=test) |
ConfigType. Tool choices are set here — for example, test.ts sets paymentProcessor.client to stripeMock so tests never hit the real Stripe API.
What ConfigType covers
ConfigType is the single source of truth for all app config. Key sections:
| Section | What it configures |
|---|---|
server | Port, session secret, cookie domain, CORS origins |
database | Postgres connection (host, port, user, password, dbname) |
redis | Redis connection URL |
tools.queue | Queue adapter type + adapter-specific config (BullMQ / SQS) |
tools.logger | Logger adapter type (Pino / Console) |
tools.metrics | Metrics adapter type + host/port (StatsD) |
tools.mailer | Mailer adapter type + API key (SendGrid / Local) |
tools.analytics | Analytics adapter type + API key (Amplitude / Local) |
tools.paymentProcessor | Payment processor type + Stripe keys (Stripe / StripeMock) |
deployment | Railway project/service IDs + deploy strategy |
Changing which tool implementation you use
When you swap a tool adapter, three things must change together:apps/backend/package.json— add/remove thetooling-*workspace dependency.apps/backend/src/configuration/<env>.ts— update theclientdiscriminator and any adapter-specific fields.- Environment variables — add/remove the env vars the new adapter reads.
make pnpm-install to update the lockfile, and make test module=backend to verify.
📖 See also: Configuration (Getting Started) for a step-by-step walkthrough with examples for every adapter.
What’s next?
- Tooling system — loaders, workspace packages, and the dynamic-import pattern.
- Configuration (Getting Started) — hands-on guide to local setup and provider swapping.
- Architecture overview — how configuration fits into the full system.