The 12-Factor App Explained — Modern Cloud-Native Best Practices
Why the 12-factor app still matters#
Written by Heroku engineers in 2011, the 12-factor methodology defines how cloud-native applications should be built. Fifteen years later, it's still the foundation of how we deploy software.
If you follow these 12 principles, your app will be deployable on any cloud, scalable horizontally, and maintainable by any team.
The 12 factors#
1. Codebase — One codebase, many deploys#
One repo per app. The same codebase deploys to dev, staging, and production. Different environments differ only by configuration.
Anti-pattern: Multiple repos for the same app, or one repo for multiple apps (that's a monorepo, which is different).
2. Dependencies — Explicitly declare and isolate#
Never rely on system-level packages being installed. Use a dependency manifest:
- Node:
package.json+package-lock.json - Python:
requirements.txtorpyproject.toml - Go:
go.mod - Rust:
Cargo.toml
Anti-pattern: "Works on my machine" because you installed something globally.
3. Config — Store config in the environment#
Database URLs, API keys, feature flags — all in environment variables, never in code.
DATABASE_URL=postgres://...
STRIPE_SECRET_KEY=sk_live_...
FEATURE_NEW_CHECKOUT=true
Anti-pattern: Committing config.production.json with secrets.
4. Backing services — Treat as attached resources#
Databases, caches, message queues, email services — all are "backing services" accessed via URL/credentials. Your app shouldn't care if the database is local or on AWS RDS.
DATABASE_URL=postgres://localhost/mydb # local
DATABASE_URL=postgres://rds.amazonaws.com/mydb # production
Swap providers without code changes.
5. Build, release, run — Strict separation#
- Build: Compile code + install dependencies → artifact
- Release: Combine artifact + config → deployable release
- Run: Execute the release in the environment
Never patch running code. Every change goes through build → release → run.
6. Processes — Execute as stateless processes#
App processes should be stateless. Any state lives in backing services (database, Redis, S3).
Anti-pattern: Storing uploaded files on the local filesystem, in-memory sessions.
Why: If a process crashes or scales down, that state is gone. Stateless processes can be restarted, scaled, or moved to another server instantly.
7. Port binding — Export services via port binding#
Your app binds to a port and serves HTTP. No need for Apache or IIS — the app is the server.
app.listen(process.env.PORT || 3000);
8. Concurrency — Scale out via the process model#
Scale horizontally by running more instances, not by making one instance bigger.
Web: 4 instances
Worker: 8 instances
Scheduler: 1 instance
Each process type scales independently.
9. Disposability — Fast startup, graceful shutdown#
Processes should start in seconds and shut down gracefully:
- Handle SIGTERM — finish current requests, close connections, then exit
- Don't hold locks during shutdown
- Make startup fast — lazy-load what you can
10. Dev/prod parity — Keep environments similar#
Same OS, same database type, same dependencies. Avoid "we use SQLite in dev and PostgreSQL in prod."
Docker makes this easy: same container runs everywhere.
11. Logs — Treat logs as event streams#
Don't write log files. Write to stdout. Let the platform (Docker, Kubernetes, Vercel) route logs to the right destination.
console.log(JSON.stringify({ event: "order_created", order_id: 123 }));
12. Admin processes — Run admin tasks as one-off processes#
Database migrations, data fixes, console sessions — run as one-off processes with the same codebase and config.
npx prisma migrate deploy # one-off migration
node scripts/backfill.js # one-off data fix
Which factors matter most#
If you only do 5, do these:
- Config in env vars (Factor 3) — The #1 security and deployment mistake
- Stateless processes (Factor 6) — Required for horizontal scaling
- Dependencies declared (Factor 2) — Reproducible builds
- Logs to stdout (Factor 11) — Plays nice with all platforms
- Dev/prod parity (Factor 10) — Catches bugs before production
Visualize your cloud-native architecture#
See how 12-factor apps connect to backing services, load balancers, and deployment pipelines — try Codelit to generate an interactive diagram.
Key takeaways#
- Stateless processes are the foundation of scalability
- Config in env vars — never commit secrets
- Logs to stdout — let the platform handle routing
- Same code, different config — dev/staging/prod differ only by env
- Fast startup + graceful shutdown — essential for auto-scaling
- The 12 factors are a minimum — modern apps also need health checks, circuit breakers, and observability
Try it on Codelit
Chaos Mode
Simulate node failures and watch cascading impact across your architecture
Cost Estimator
See estimated AWS monthly costs for every component in your architecture
GitHub Integration
Paste a repo URL and generate architecture from your actual codebase
Related articles
Try these templates
Netflix Video Streaming Architecture
Global video streaming platform with adaptive bitrate, CDN distribution, and recommendation engine.
10 componentsSearch Engine Architecture
Web-scale search with crawling, indexing, ranking, and sub-second query serving.
8 componentsMultiplayer Game Backend
Real-time multiplayer game server with matchmaking, state sync, leaderboards, and anti-cheat.
8 componentsBuild this architecture
Generate an interactive architecture for The 12 in seconds.
Try it in Codelit →
Comments