Backend5 min read

Twelve-Factor App

Build cloud-native applications with twelve-factor methodology - environment config, stateless processes, disposability, and dev/prod parity.

Twelve-FactorCloud NativeDevOpsConfigurationStateless

skill: Twelve-Factor App category: Backend tags: [Twelve-Factor, Cloud Native, DevOps, Configuration, Stateless] readingTime: 5

The twelve-factor methodology defines the practices that make web applications portable, scalable, and maintainable in cloud environments. Not all twelve factors apply to every application, but factors I (codebase), III (config), VI (processes), XI (logs) are nearly universal - violating them creates operational headaches.

Workflow

  1. Factor III: Store config in the environmentConfig that varies between deployments (API keys, DB URLs) must not be in code. Hard-coded config requires code changes and deployments to change behavior.
  2. Factor VI: Execute the app as stateless processesStateless processes scale horizontally - add more instances to handle more load. Stateful processes (storing session in memory) break horizontal scaling and lose data on restart.
  3. Factor IX: Maximize robustness with disposabilityProcesses should start fast and shut down gracefully - cloud environments restart containers frequently (deploys, scaling, health check failures). Graceful shutdown completes in-flight requests.
  4. Factor XI: Treat logs as event streamsApplications should write logs to stdout - the infrastructure (Docker, Kubernetes, systemd) captures and routes them. Applications should not manage log files, rotation, or shipping.
  5. Factor X: Dev/prod parityDifferences between development and production environments cause "works on my machine" bugs. Minimize the gap - same database, same OS, same configuration management.

Output Format

Twelve-factor: zod env validation at startup, Redis session for stateless processes, SIGTERM graceful shutdown, JSON logs to stdout, and Docker Compose dev/prod parity.

Config: z.object({ DATABASE_URL, JWT_SECRET }).parse(process.env)
State: express-session → RedisStore (not in-memory)
Shutdown: process.on("SIGTERM") → server.close() → db.end() → process.exit(0)
Logs: winston Console transport → stdout → infrastructure routes
Dev: docker-compose with same postgres/redis versions as production

Examples

Input

Output

Edge Cases & Gotchas

  • SIGTERM vs. SIGKILL - SIGTERM (software terminate) can be caught for graceful shutdown. SIGKILL cannot - it immediately kills the process. Kubernetes sends SIGTERM then waits terminationGracePeriodSeconds (default 30s), then SIGKILL.
  • NODE_ENV=production for performance - Express disables certain features (stack traces, view cache) in production mode. Always set NODE_ENV=production in production containers.
  • Log aggregation pipelines - stdout logs are ephemeral - containers are killed and logs are lost. In Kubernetes, use Fluentd/Fluentbit DaemonSet to ship pod logs to Elasticsearch/Loki/Datadog before pod termination.
  • Config vs. secrets - The twelve-factor "config in environment" rule applies to both config and secrets. But for secrets, environment variables should be sourced from Secrets Manager, not hardcoded in docker-compose or k8s deployment manifests.

When to Break These Rules

  • Use file-based config (config.yaml) for configuration that is complex, hierarchical, and doesn't vary per environment - twelve-factor envvars are best for per-environment secrets and URLs, not complex nested config trees.
  • Write log files locally for applications that need audit logs with strict retention requirements - ship to external store but also keep a local copy with proper rotation (logrotate).

Reference Files

  • https://12factor.net/
  • https://www.heroku.com/

More skills in this library

Browse all technical skills - Mobile, AI/ML, Web, Backend, Design, and Product.