| name | twelve-factor |
| description | Guide for 12-Factor cloud-native applications. Use when designing microservices, configuring containers, deploying to Kubernetes, or following cloud-native patterns. |
| license | MIT |
12-Factor App Methodology
Guide for building scalable, maintainable, and portable cloud-native applications following the 12-Factor App principles and modern extensions.
When to Activate
Use this skill when:
- Designing or refactoring cloud-native applications
- Building applications for Kubernetes deployment
- Setting up CI/CD pipelines
- Implementing microservices architecture
- Migrating applications to containers
- Reviewing architecture for cloud readiness
- Troubleshooting deployment or scaling issues
- Working with environment configuration
The 12 Factors
I. Codebase
One codebase tracked in revision control, many deploys
- Single Git repository for the application; every environment deploys from it
- Environment-specific config lives outside the code
- Use GitOps (ArgoCD, Flux) for deployment automation
Violations: multiple repositories for one application, per-environment codebases, copying code between repositories. Fix: consolidate to one repository and move the differences into environment config.
II. Dependencies
Explicitly declare and isolate dependencies
- Declare every dependency in the package manager manifest; never rely on system-wide packages
- Commit lock files for reproducible builds (
package-lock.json, mix.lock, Cargo.lock, go.sum)
- Multi-stage container builds isolate build-time dependencies from the runtime image
Worked Dockerfile and per-language manifest list: references/factor-examples.md.
III. Config
Store config in the environment
All configuration comes from environment variables — anything that varies between deploys: credentials, hostnames, ports, pool sizes, backing service URLs, model names.
# Elixir - config/runtime.exs
config :my_app, MyApp.Repo,
hostname: System.get_env("DATABASE_HOST") || "localhost",
password: System.fetch_env!("DATABASE_PASSWORD"),
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10")
What makes a violation, and the smallest correct fix:
- Hardcoded value that differs (or could differ) between deploys → read it from an environment variable, with a default only when a safe dev default exists
- Hardcoded model name, API endpoint, or service hostname → environment variable; model names are config, not code
- Config file with real values committed to version control → environment variables plus a committed
.example template
- Environment-specific code path (
if env == "production") → one code path driven by a config value
Litmus test from 12factor.net: the codebase could be made open source at any moment without compromising any credentials.
Kubernetes ConfigMap/Secret wiring: references/kubernetes.md.
IV. Backing Services
Treat backing services as attached resources
- Databases, queues, caches, and third-party APIs all attach via URLs in environment variables
- No distinction between local and third-party services
- Swapping a backing service is a configuration change only — never a code change
V. Build, Release, Run
Strictly separate build and run stages
- Build: convert code to executable bundle
- Release: combine build with config
- Run: execute in target environment
- Releases are immutable and uniquely identified (git SHA, semver)
- Roll back by redeploying a previous release, never by modifying one
- Build artifacts stay separate from runtime config
CI/CD pipeline example: references/factor-examples.md.
VI. Processes
Execute the app as one or more stateless processes
- Processes are stateless and share-nothing; persistent state lives in backing services
- No sticky sessions, no local filesystem for persistent data
- Violation: in-memory session or state store → move it to Redis or the database
Session-store example: references/factor-examples.md. Deployment manifest: references/kubernetes.md.
VII. Port Binding
Export services via port binding
- Bind to
0.0.0.0, never localhost; take the port number from the environment
- HTTP server library embedded in the app — no reliance on runtime injection (Apache, Nginx)
VIII. Concurrency
Scale out via the process model
- Scale horizontally by adding processes, not vertically by enlarging them
- Distinct process types (web, worker, scheduler) scale independently
- The OS or platform process manager owns processes — never daemonize or write PID files
IX. Disposability
Maximize robustness with fast startup and graceful shutdown
- Minimize startup time (under 10 seconds ideal) — fast startup enables rapid scaling
- Handle SIGTERM: finish in-flight requests, close connections, then exit
- Stay robust against sudden death
Graceful-shutdown example: references/factor-examples.md.
X. Dev/Prod Parity
Keep development, staging, and production as similar as possible
- Same backing service types in dev and prod (not SQLite in dev, Postgres in prod)
- Containers ensure environment consistency; infrastructure as code for reproducibility
- Same deployment process for all environments; minimize the time gap between dev and production
Docker Compose dev-environment example: references/factor-examples.md.
XI. Logs
Treat logs as event streams
- Write unbuffered to stdout/stderr; never manage or rotate log files in the app
- Use structured logging (JSON) with correlation IDs for tracing
- The platform routes logs (Fluentd, Logstash) — never send directly to an aggregation service from app code
XII. Admin Processes
Run admin/management tasks as one-off processes
- Migrations, consoles, and one-time scripts use the same codebase, config, and environment as regular processes
- Run against a release, not development code
- Use the platform scheduler for recurring tasks; ship admin code with application code
Kubernetes Job/CronJob examples: references/kubernetes.md.
Modern Extensions (Beyond 12)
Three extensions round out contemporary cloud-native practice — full detail and examples in references/modern-extensions.md:
- XIII. API First — design and document APIs (OpenAPI) before implementation; contract-first development
- XIV. Telemetry —
/metrics endpoint, distributed tracing (OpenTelemetry), health check endpoints
- XV. Security — OAuth 2.0/OIDC, RBAC, secrets in environment never in code, TLS everywhere, security scanning in CI/CD
Common Patterns
Configuration Validation
Validate required configuration at startup — fail fast, naming the missing variables:
function validateConfig() {
const required = ['DATABASE_URL', 'JWT_SECRET', 'REDIS_URL'];
const missing = required.filter(key => !process.env[key]);
if (missing.length > 0) {
throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
}
}
validateConfig();
Health checks, graceful degradation, and the troubleshooting guide: references/operations.md.
Anti-Patterns to Avoid
❌ Environment-Specific Code Paths
if (process.env.NODE_ENV === 'production') { }
const timeout = parseInt(process.env.TIMEOUT || '5000');
❌ Local File Storage
fs.writeFile('/tmp/uploads/' + filename, data);
await s3.putObject({ Bucket: process.env.S3_BUCKET, Key: filename, Body: data });
❌ In-Memory State
const sessions = new Map();
const session = await redis.get(`session:${sessionId}`);
❌ Hardcoded Dependencies
const db = connect('localhost:5432');
const db = connect(process.env.DATABASE_URL);
Best Practices Summary
- Environment variables for all configuration
- Stateless processes that can scale horizontally
- Structured logging to stdout
- Containers for development parity
- Automated CI/CD pipelines
- Health checks for orchestration
- Graceful shutdown handling
- Fast startup times (< 10s)
- Immutable releases with unique IDs
- Comprehensive monitoring and telemetry
Resources
Key Insights
"The twelve-factor methodology can be applied to apps written in any programming language, and which use any combination of backing services (database, queue, memory cache, etc)."
"A twelve-factor app never relies on implicit existence of state on the filesystem. Even if a process has written something to disk, it must assume that file won't be available on the next request."
Design applications from day one to be cloud-native, scalable, and maintainable.
References
references/factor-examples.md — per-factor worked code examples (Dockerfile, runtime config, session storage, graceful shutdown, Docker Compose, structured logging, CI/CD pipeline)
references/kubernetes.md — Kubernetes manifests per factor (ConfigMaps, Secrets, Deployments, HPA, Jobs, probes) and Kubernetes-specific best practices
references/modern-extensions.md — API First, Telemetry, and Security extensions with examples
references/operations.md — health check endpoints, graceful degradation, troubleshooting guide
references/infrastructure-conventions.md — NGINX upstream over community ingress; Kustomize + Helm layout; single universal secret store; IaC over manual UI; bind all interfaces in prod