Twelve-Factor App
debt(d7/e7/b7/t5)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints list semgrep and dockerlint, but automated detection is explicitly marked 'no'. Violations like config in code, local filesystem state, or dev/prod parity gaps typically surface through manual code review, architectural audits, or operational pain in production — not through routine static analysis catching them reliably.
Closest to 'cross-cutting refactor across the codebase' (e7). The quick_fix describes an audit across multiple factors — config in env vars, stateless processes, admin tasks, logs to stdout. Common mistakes span session handling, hardcoded URLs, filesystem state, and process architecture. Remediating a non-12-factor app meaningfully touches deployment configuration, application code, infrastructure, and CI/CD pipelines across many files and contexts.
Closest to 'strong gravitational pull' (b7). The methodology applies to web, cli, and queue-worker contexts — the full breadth of PHP deployment contexts. Every architectural decision about config management, process statefulness, logging, and service wiring is shaped by whether the app follows 12-factor principles. Gaps impose a persistent drag across all deployment, scaling, and onboarding work streams.
Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The misconception field captures a real and common wrong belief: that 12-factor is only for microservices. Developers building monoliths often skip these principles thinking they don't apply, leading to config-in-code, stateful processes, and dev/prod divergence — problems they eventually learn about the hard way when scaling or containerising.
Also Known As
TL;DR
Explanation
The Twelve-Factor App methodology (Heroku, 2011) defines: I. Codebase (one repo), II. Dependencies (declared, isolated), III. Config (in environment), IV. Backing services (attached resources), V. Build/release/run (strict separation), VI. Processes (stateless), VII. Port binding (self-contained), VIII. Concurrency (scale-out), IX. Disposability (fast startup/graceful shutdown), X. Dev/prod parity, XI. Logs (treated as event streams), XII. Admin processes. For PHP, Factor III (config in environment) and Factor VI (stateless processes) have the largest security and scalability implications.
Diagram
flowchart TD
subgraph The 12 Factors
F1[1 Codebase<br/>one repo]
F2[2 Dependencies<br/>explicitly declared]
F3[3 Config<br/>in environment]
F4[4 Backing Services<br/>attached resources]
F5[5 Build Release Run<br/>strict separation]
F6[6 Processes<br/>stateless]
F7[7 Port Binding<br/>self-contained]
F8[8 Concurrency<br/>process model]
F9[9 Disposability<br/>fast startup]
F10[10 Dev/Prod Parity<br/>keep similar]
F11[11 Logs<br/>treat as streams]
F12[12 Admin Processes<br/>one-off tasks]
end
style F1 fill:#238636,color:#fff
style F3 fill:#238636,color:#fff
style F6 fill:#1f6feb,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Storing config in code instead of environment variables — factor III.
- Local filesystem state that does not survive container restarts — factor VI (stateless processes).
- Admin tasks (migrations, scripts) run inside the web server process — factor XII (run admin as one-off processes).
- Hardcoded service URLs instead of environment-variable-configured backing services — factor IV.
Code Examples
// Violates factor III — config in code:
define('DB_HOST', 'db.prod.internal'); // Should be: getenv('DB_HOST')
define('API_KEY', 'sk-prod-abc123'); // Should be: getenv('API_KEY')
// Violates factor VI — filesystem state:
file_put_contents('/tmp/user_sessions/' . $id, $data); // Lost on restart
# Key factors and PHP implications:
# I — Codebase: one repo, deploy to many envs via env vars
# II — Dependencies: composer.json, no system-wide packages
composer install --no-dev
# III — Config: env vars, never hardcoded
$dsn = sprintf('pgsql:host=%s;dbname=%s', $_ENV['DB_HOST'], $_ENV['DB_NAME']);
# VI — Processes: stateless — no local filesystem writes
# Upload files → S3, sessions → Redis (not filesystem)
ini_set('session.handler', 'redis');
# VII — Port binding: PHP-FPM binds to a port, nginx proxies
# IX — Disposability: fast startup (OPcache), graceful shutdown
# XI — Logs: write to stdout, let platform aggregate
error_log = /dev/stderr ; in php.ini