The 12-Factor App
The 12-Factor App is a methodology for building modern Software-as-a-Service (SaaS) and cloud-native applications. Originally created by engineers at Heroku, it has become the gold standard for building resilient web applications.
Applications built using this methodology:
- Use declarative formats for setup automation.
- Have a clean contract with the underlying OS, offering maximum portability.
- Are suitable for deployment on modern cloud platforms.
- Minimize divergence between development and production for continuous deployment agility.
- Scale up seamlessly without significant architectural changes.
Quick Reference
Section titled “Quick Reference”| # | Factor | One-Line Summary |
|---|---|---|
| 1 | Codebase | One repo, many deploys. |
| 2 | Dependencies | Declare all dependencies explicitly. |
| 3 | Config | Store config in environment variables, not code. |
| 4 | Backing Services | Treat databases, queues, and caches as swappable resources. |
| 5 | Build, Release, Run | Strictly separate build, release, and run stages. |
| 6 | Processes | Run stateless, share-nothing processes. |
| 7 | Port Binding | Export services via port binding; be self-contained. |
| 8 | Concurrency | Scale out horizontally via more processes. |
| 9 | Disposability | Fast startup, graceful shutdown, crash-safe. |
| 10 | Dev/Prod Parity | Keep all environments as similar as possible. |
| 11 | Logs | Stream logs to stdout; never manage log files yourself. |
| 12 | Admin Processes | Run admin tasks as one-off processes in the same environment. |
The 12 Factors
Section titled “The 12 Factors”1. Codebase
Section titled “1. Codebase”“One codebase tracked in version control, many deploys.”
A single codebase should be used to manage all deployments (development, staging, production) of the app. Do not use separate codebases for different environments. This ensures consistency and reduces configuration drift.
2. Dependencies
Section titled “2. Dependencies”“Explicitly declare and isolate dependencies.”
Never rely on the implicit existence of system-wide packages. Declare all dependencies completely and exactly via a dependency declaration manifest (e.g., package.json, requirements.txt, pom.xml).
3. Config
Section titled “3. Config”“Store config in the environment.”
Strictly separate configuration from code. Configuration varies substantially across environments, but code does not. Store database credentials, API keys, and external service URLs as Environment Variables (export DATABASE_URL=...), never hardcoded in the repository.
4. Backing Services
Section titled “4. Backing Services”“Treat backing services as attached resources.”
A backing service is any service the app consumes over the network (databases, SMTP services, caching systems, message queues). The app should make no distinction between local and third-party services. They are simply accessed via a URL or locator stored in the config, meaning they can be swapped out without code changes.
5. Build, Release, Run
Section titled “5. Build, Release, Run”“Strictly separate build and run stages.”
- Build: Compiles code, fetches dependencies, and creates an executable artifact.
- Release: Combines the build artifact with the deploy’s specific configuration.
- Run: Launches the application in the execution environment. This strict separation prevents code mutations at runtime.
6. Processes
Section titled “6. Processes”“Execute the app as one or more stateless processes.”
The app is executed in the execution environment as one or more processes. These processes must be stateless and share-nothing. Any data that needs to persist must be stored in a stateful backing service, typically a database. Stickiness (sticky sessions) should never be relied upon.
7. Port Binding
Section titled “7. Port Binding”“Export services via port binding.”
The web app is completely self-contained and does not rely on runtime injection of a webserver into the execution environment. The app exports HTTP as a service by binding to a port, and listening to requests coming in on that port.
8. Concurrency
Section titled “8. Concurrency”“Scale out via the process model.”
Scale your application horizontally by adding more processes (scaling out) rather than simply making a single process larger (scaling up). Because the app is stateless (Factor 6), you can safely run multiple instances behind a load balancer.
9. Disposability
Section titled “9. Disposability”“Maximize robustness with fast startup and graceful shutdown.”
The app’s processes should be disposable, meaning they can be started or stopped at a moment’s notice. Fast startup minimizes impact during scaling and deployments. Processes should shut down gracefully (handling SIGTERM) by ceasing to listen for new requests and finishing current ones.
10. Dev/Prod Parity
Section titled “10. Dev/Prod Parity”“Keep development, staging, and production as similar as possible.”
Keep the gap between development and production as small as possible. Use the same backing services (e.g., use PostgreSQL locally if you use it in production) and strive for continuous deployment where code written today is deployed today.
11. Logs
Section titled “11. Logs”“Treat logs as event streams.”
Logs are the stream of aggregated, time-ordered events. A 12-factor app never concerns itself with routing or storage of its output stream. It should not attempt to write to or manage log files. Instead, each running process writes its event stream, unbuffered, to standard output (stdout). The execution environment collects, routes, and stores these logs (e.g., in an ELK stack or Datadog).
12. Admin Processes
Section titled “12. Admin Processes”“Run admin/management tasks as one-off processes.”
Any database migrations, console scripts, or one-off administrative tasks should be run in an identical environment as the regular long-running processes of the app (same codebase, same configuration).