Production Architecture and Scalability
Design resilient Node.js systems with horizontal scaling, reverse proxies, containers, configuration management, rate limiting, reliability patterns, and distributed systems concepts.
Horizontal Scaling
Horizontal scaling means running multiple instances of an application and distributing traffic among them. This improves capacity and can improve availability when instances are independently replaceable.
Stateless application servers make horizontal scaling easier. If state must be shared, use an external system such as a database, cache, or message broker rather than relying on process-local memory.
- Stateless services are easier to scale horizontally.
- Shared state should live in appropriate external infrastructure.
- Load balancing distributes traffic across healthy instances.
Why are stateless Node.js servers easier to scale horizontally?
Rate Limiting, Timeouts, Retries, and Circuit Breakers
Reliable services protect themselves and their dependencies with timeouts, rate limits, bounded retries, and circuit breakers. A retry without limits can amplify an outage by causing a retry storm.
Retries should generally use exponential backoff with jitter and should only be applied to operations that are safe to retry or made idempotent.
Unbounded retries multiply traffic against an already unhealthy dependency. Use bounded retries, backoff, jitter, and appropriate timeouts.
- Every external call should have an appropriate timeout.
- Retries need limits and backoff.
- Rate limiting protects resources from excessive traffic.
Why should retries use exponential backoff?
Containerizing Node.js Applications
Containers package an application and its runtime dependencies into a reproducible deployment unit. A production Node.js image should use a suitable base image, install only required dependencies, run as a non-root user when practical, and avoid copying secrets into the image.
Container orchestration systems can provide scaling, health checks, rolling deployments, networking, and resource management.
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
USER node
EXPOSE 3000
CMD ['node', 'server.js']node user, and starts the service.- Do not bake secrets into container images.
- Use deterministic dependency installation in builds.
- Containers should be disposable and externally configurable.
Where should production secrets normally come from in a containerized application?