Skip to content

twelve-factor app

The twelve-factor app is a methodology for building software-as-a-service applications as twelve declarative practices. The factors make a service portable across runtimes, scalable through process replication, and easy to deploy to a modern cloud platform.

The methodology was published by Adam Wiggins at Heroku in 2011 and last revised in 2017. Its language-agnostic vocabulary now shows up in almost every cloud-native deployment discussion a Python developer joins.

The twelve factors are:

  1. Codebase: one codebase tracked in version control, many deploys.
  2. Dependencies: explicitly declare and isolate dependencies.
  3. Config: store config in environment variables.
  4. Backing services: treat backing services as attached resources.
  5. Build, release, run: strictly separate the build and run stages.
  6. Processes: execute the app as one or more stateless processes.
  7. Port binding: export services by binding to a port.
  8. Concurrency: scale out via the process model.
  9. Disposability: maximize robustness with fast startup and graceful shutdown.
  10. Dev/prod parity: keep development, staging, and production as similar as possible.
  11. Logs: treat logs as event streams.
  12. Admin processes: run admin and management tasks as one-off processes.

How It Shows Up in Practice

The twelve factors are the implicit rules behind a Heroku, Render, Fly, Railway, AWS App Runner, Google Cloud Run, or Kubernetes deployment. Each platform’s happy path assumes a single repository and a declared dependency manifest such as requirements.txt or pyproject.toml.

Configuration arrives as environment variables. Stateless web processes can be replaced freely. Logs go to stdout. A database connection is expressed as a URL pointed at by an env var.

Config and logs, Factors 3 and 11, are the most visible in a Python codebase. A twelve-factor service reads its configuration from os.environ instead of a checked-in settings module, and emits unbuffered log lines on stdout so the platform can aggregate, rotate, and route them:

Language: Python
import logging
import os
import sys

DATABASE_URL = os.environ.get("DATABASE_URL", "postgres://localhost/app")
LOG_LEVEL = os.environ.get("LOG_LEVEL", "INFO")
DEBUG = os.environ.get("DEBUG", "0") == "1"

logging.basicConfig(
    stream=sys.stdout,
    level=LOG_LEVEL,
    format="%(asctime)s %(levelname)s %(name)s %(message)s",
)
log = logging.getLogger("checkout")
log.info(
    "starting service db=%s debug=%s",
    DATABASE_URL.rsplit("/", 1)[-1],
    DEBUG,
)
Language: Program Output
2026-05-27 12:00:00,000 INFO checkout starting service db=app debug=False

Adam Wiggins phrased the config rule as a litmus test: an app has its configuration correctly factored out if the entire codebase could be open-sourced without leaking a single credential.

Common Pitfalls

The twelve factors are easy to violate in ways that only hurt at scale. The most common pitfall in Python services is keeping state in process memory, such as caching session tokens in a module-level dict, then deploying multiple replicas behind a load balancer.

The cache is not shared, so users see logged-out sessions whenever the load balancer routes them to a different replica. Factor 6 explicitly rejects this design and routes session state to a stateful backing service such as Redis or a database.

Other recurring slips include committing secrets to settings.py, writing log files to disk, or running database migrations from inside the web process instead of as a one-off admin command. Pinning to a system-wide Python install rather than an isolated environment violates Factor 2.

The methodology predates containerization but maps cleanly onto it. A Dockerfile builds the immutable artifact for Factor 5. Environment variables fed at docker run time satisfy Factor 3. A docker stop that sends SIGTERM exercises Factor 9.

Some factors fit twelve-factor’s original PaaS context better than they fit modern serverless or stateful workloads, particularly the stdout-only log handling and strict statelessness. Even so, the vocabulary remains the shared baseline almost every cloud platform expects an application to meet.

Tutorial

Deploying a Python Flask Example Application Using Heroku

In this step-by-step tutorial, you'll learn how to create a Python Flask example web application and deploy it using Heroku.

intermediate devops flask web-dev

For additional information on related topics, take a look at the following resources:


By Martin Breuss • Updated June 1, 2026