12-factor app
The 12-factor app is a methodology for building software-as-a-service applications that are designed to be deployed as cloud services. It was distilled in 2011 by Adam Wiggins and other engineers at Heroku from their experience building and operating the Heroku platform. The methodology is documented as a short, opinionated manifesto at https://12factor.net/.
The goal of the methodology is to minimize the friction of modern application development and operation. It collects a set of design principles that, taken together, make applications portable across deployment environments, friendly to continuous deployment, and able to scale out cleanly without architectural rework. Many of the same principles recur in microservices design, and the 12-factor methodology is often cited as a precursor of the cloud-native style that containers and orchestrators later productized.
The twelve factors are guidelines, not a checklist. Each addresses a particular class of problem that the authors observed recurring across SaaS applications.
- I. Codebase. One codebase tracked in revision control, with many deploys derived from it. A single app may have many deployed instances (staging, production, and so on) that all share one codebase, but multiple apps must not share a codebase.
- II. Dependencies. Declare and isolate dependencies explicitly. An app should never rely on the implicit existence of system-wide packages, and its dependency manifest makes the build deterministic across environments.
- III. Config. Store configuration in the environment. Anything that varies between deploys – credentials, resource handles, feature toggles – should be injected via environment variables rather than baked into the codebase, keeping the same build artifact deployable anywhere. This is the application-level counterpart to the systems practice of configuration management.
- IV. Backing services. Treat attached resources – databases, message brokers, caching layers, email services – as interchangeable, addressable backing services consumed over the network. Swapping a local database for a managed one should require only a configuration change.
- V. Build, release, run. Strictly separate the build stage (which compiles source into a immutable artifact) from the release stage (which combines the build with config to form a release) and the run stage (which executes the release). Releases are append-only and immutable, which makes rollbacks a matter of restoring a prior release.
- VI. Processes. Execute the app as one or more stateless processes. Any state that needs to persist must be held in a backing service, so that any process can be killed or replaced without losing data that the next request depends on.
- VII. Port binding. Export services by binding to a port, rather than running inside a host web server. The app is self-contained and becomes a backing service to others that connect to its port.
- VIII. Concurrency. Scale out by adding processes, exploiting the operating system’s concurrency model rather than threads alone. Different workloads (web requests, background jobs, scheduled tasks) run as separate process types that can be scaled independently.
- IX. Disposability. Maximize robustness with fast startup and graceful shutdown. Processes should start quickly and exit cleanly on a termination signal, which makes them safe to scale elastically and to relocate at will.
- X. Dev/prod parity. Keep development, staging, and production as similar as possible, across time, personnel, and backing services. Small gaps between environments are where deployment surprises hide.
- XI. Logs. Treat logs as an append-only event stream.
The app writes unbuffered events to
stdoutand leaves aggregation, routing, and long-term storage to the platform. - XII. Admin processes. Run administrative and maintenance tasks – database migrations, one-off scripts, data imports – as short-lived processes that use the same release environment as the app, executed in an identical setup to production.
Note
The 12-factor methodology predates the widespread adoption of containerization and infrastructure as code, but its principles map cleanly onto both: a container image is a natural build artifact, an environment-variable config is trivial to inject into a container, and a stateless, disposable process is exactly what an orchestrator schedules.
See also
- Microservices
- Cloud computing
- Containerization
- Stateless design
- Continuous deployment
- Concurrency
- Logging
- Version control
References
- Wiggins, Adam (2011). The Twelve-Factor App.