Skip to content

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.
#FactorOne-Line Summary
1CodebaseOne repo, many deploys.
2DependenciesDeclare all dependencies explicitly.
3ConfigStore config in environment variables, not code.
4Backing ServicesTreat databases, queues, and caches as swappable resources.
5Build, Release, RunStrictly separate build, release, and run stages.
6ProcessesRun stateless, share-nothing processes.
7Port BindingExport services via port binding; be self-contained.
8ConcurrencyScale out horizontally via more processes.
9DisposabilityFast startup, graceful shutdown, crash-safe.
10Dev/Prod ParityKeep all environments as similar as possible.
11LogsStream logs to stdout; never manage log files yourself.
12Admin ProcessesRun admin tasks as one-off processes in the same environment.

“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.

“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).

“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.

“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.

“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.

“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.

“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.

“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.

“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.

“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.

“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).

“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).