The Twelve-Factor App: Principles for Modern Application Development
Published in 2011 by the founders of Heroku, the Twelve-Factor App methodology defines 12 fundamental principles for developing modern SaaS applications. In the cloud native era, these principles are more relevant than ever.
Why Twelve-Factor?
These principles solve:
- Differences between development and production environments
- Scaling difficulties
- Deployment complexity
- New team member onboarding time
The 12 Principles
I. Codebase — One Codebase, Many Deploys
Each application lives in a single code repository. Multiple deploys (staging, production) can exist, but the codebase is singular.
II. Dependencies — Explicitly Declare Dependencies
All dependencies must be explicitly declared. No implicit system dependencies:
{
"dependencies": {
"next": "14.0.0",
"react": "18.2.0"
}
}
III. Config — Store Config in Environment Variables
Configuration lives in environment variables, not in code:
DATABASE_URL=postgresql://user:pass@host:5432/db
API_KEY=sk-abcdef123456
IV. Backing Services — Treat as Attached Resources
Databases, caches, and email services should be swappable via configuration:
Dev: DATABASE_URL=postgres://localhost/dev
Prod: DATABASE_URL=postgres://cloud-sql/prod
No code changes required.
V. Build, Release, Run — Strictly Separate Stages
Build: Compile code, resolve deps → Artifact
Release: Artifact + Config → Release
Run: Execute release → Running app
VI. Processes — Run as Stateless Processes
Applications should run as stateless processes. Session data and files should be stored in external services (Redis, database).
VII. Port Binding — Export Services via Port Binding
The application should host its own web server and serve via a specific port:
app.listen(process.env.PORT || 3000);
VIII. Concurrency — Scale Out via Processes
Scale horizontally by adding more processes:
Web: 2 instances
Worker: 4 instances
Cron: 1 instance
IX. Disposability — Fast Startup, Graceful Shutdown
Applications should start in seconds and handle graceful shutdown:
process.on('SIGTERM', async () => {
await server.close();
await db.disconnect();
process.exit(0);
});
X. Dev/Prod Parity — Keep Environments Similar
Development, staging, and production environments should be as similar as possible. Use Docker for environment standardization.
XI. Logs — Treat as Event Streams
Logs go to stdout, not files. External tools handle log collection and analysis:
// ✅ Correct
console.log(JSON.stringify({ level: 'info', message: 'Order created' }));
// ❌ Wrong
fs.appendFileSync('/var/log/app.log', message);
XII. Admin Processes — Run as One-Off Processes
Database migrations, scripts, and cleanup tasks run as one-off processes:
npm run migrate
npm run seed
In Practice: BilgeOne
How BilgeOne applies these principles:
| Principle | Implementation | |-----------|---------------| | Codebase | GitHub monorepo | | Dependencies | package.json | | Config | .env + Cloud Run env vars | | Backing Services | Supabase (PostgreSQL, Auth) | | Build/Release | GitHub Actions + Docker | | Processes | Stateless Next.js | | Port Binding | Cloud Run port injection | | Concurrency | Cloud Run auto-scaling | | Disposability | Fast container startup | | Parity | Docker standardization | | Logs | Cloud Run stdout logging | | Admin | npm scripts |
Conclusion
The Twelve-Factor App principles are the foundational guide for cloud-era software development. Applications built following these principles are more scalable, maintainable, and portable.
Learn Cloud Native and 12-Factor principles on the DevOps career path at LabLudus.