The Twelve-Factor App: still the cleanest playbook for Heroku
Heroku doesn't ship a Well-Architected framework like AWS or Salesforce. It has something older and more elegant — Adam Wiggins's Twelve-Factor App, still the most concise architectural posture for anything running on a PaaS.
Heroku doesn’t maintain a “Well-Architected” framework the way AWS and Salesforce do. What it has, instead, is the Twelve-Factor App — written by Heroku’s co-founder Adam Wiggins around 2011, refined since, and still uncannily current. It’s a single short web page describing twelve architectural commitments, each of which produces a specific operational property when adopted.
The Twelve-Factor App predates Kubernetes, container orchestration, and serverless. Most of its predictions held anyway, which is the test for whether an architectural document was actually doing work.
Twelve factors, three categories
The factors group naturally into three groups — what to do at build time, what your runtime should look like, and how to manage and observe the running app.
Development & configuration
I. Codebase. One codebase tracked in version control. Multiple deploys (prod, staging, dev) from that single source. Two codebases for “the same app” is a tell that something has drifted; one codebase deployed to many places is the default.
II. Dependencies. All dependencies declared explicitly in manifests (Gemfile, requirements.txt, package.json). No implicit reliance on system packages. The system Python is not your Python.
III. Config. Credentials, ports, and environment-specific values are stored as environment variables — never hardcoded, never committed. The test: could you make this same artifact run in staging and prod with no code changes?
IV. Backing services. Databases, caches, and queues are accessed via configuration URLs. They’re resources you swap in and out, not parts of the app. Replacing your Postgres with a managed one shouldn’t require a code change.
X. Dev/prod parity. Minimize gaps between dev, staging, and prod in time, personnel, and tools. The further your dev environment drifts from prod, the more often you ship subtle bugs that “worked on my machine.”
Runtime
V. Build, release, run. Strictly separate stages. Build turns source into a runnable artifact. Release combines that artifact with environment config. Run executes it. Don’t merge them. A successful build but a failed release is recoverable; mixing them is not.
VI. Processes. The app runs as stateless processes. Any persistent state lives in a backing service. If you can’t kill any single instance without affecting users, that’s a stateful instance pretending to be stateless.
VII. Port binding. The app is self-contained and exports services by binding to a port. No external web server daemon embedded in the deploy. This is what makes a Twelve-Factor app a citizen of any reasonable PaaS — the platform owns the routing.
VIII. Concurrency. Scaling is achieved by running more processes of a specific type (web, worker), not by making individual processes bigger. Process types map to workload types; you scale them independently.
IX. Disposability. Processes start fast and shut down gracefully on SIGTERM. Disposability is what makes elastic scaling and rolling deploys work. If your process takes 90 seconds to start, you’ve lost autoscaling.
Management & visibility
XI. Logs. The app writes unbuffered to stdout. The platform (Heroku, in this case) collates all process and platform output into a single aggregated log stream you can drain elsewhere. Logging libraries that write to files in container instances are an anti-pattern in a Twelve-Factor world.
XII. Admin processes. Administrative tasks (migrations, one-off scripts) run as one-off processes in the production environment, using the same codebase and config as the running app. Different code paths for “admin” things accumulate drift you can’t easily test.
How the factors map to Heroku concepts
Heroku didn’t invent dynos and config vars to be artistic; the platform mirrors the framework one-to-one.
| Heroku concept | Twelve-Factor factor |
|---|---|
| Dynos (web, worker, one-off) | VI Processes, VIII Concurrency, IX Disposability, XII Admin Processes |
| Buildpacks / slugs | V Build/Release/Run, II Dependencies |
| Config Vars | III Config |
| Procfile | VII Port Binding, VIII Concurrency |
| Add-ons (Postgres, Redis, Kafka) | IV Backing Services |
| Log Drains | XI Logs |
| Pipelines & Review Apps | I Codebase, X Dev/Prod Parity |
Heroku is one of the few platforms where the framework is hard to violate — most Twelve-Factor anti-patterns are simply not expressible. You can’t SSH into a dyno and edit a config file that survives the next deploy, because the next deploy starts a new dyno from a slug. The platform makes statelessness the default, which is the entire game.
How it compares to AWS and Salesforce
| Aspect | Heroku 12-Factor | AWS | Salesforce |
|---|---|---|---|
| Year published | ~2011 | 2015 | 2022 |
| Structure | 3 categories, 12 factors | 5 pillars | 3 capabilities |
| Scope | App / PaaS | Cloud infrastructure | Customer 360 platform |
| Language-specific? | No (polyglot) | No | Yes (Apex / platform) |
| Priority order | None explicit | None explicit | Yes — Trusted is first |
The Twelve-Factor App is the most prescriptive of the three. AWS and Salesforce give you a vocabulary to reason about trade-offs; Twelve-Factor gives you twelve specific commitments and tells you to make all of them. That works because the scope is narrower — app design, on a PaaS, in 2026 — and because the factors are mutually supporting. Skip one and several of the others lose their leverage.
What to do this week
Pick one running app. Walk down the twelve factors. For each one, give it a yes/no, with a note where the answer is “no”. You’ll usually find that two or three factors are missed in ways that explain operational pain you’d already noticed. Twelve-Factor reviews are most useful as a way to translate vague unhappiness into specific architectural debt.
For the broader Salesforce framing, see Salesforce Well-Architected: trust first, ease second, adaptability third. For the cloud-infrastructure framing, see The AWS Well-Architected Framework, distilled.