The twelve-factor app, revisited
The twelve-factor app remains a useful checklist for deployable web services, but it should not be treated as a complete architecture model. Its value is in the constraints it mak…
The twelve-factor app remains a useful checklist for deployable web services, but it should not be treated as a complete architecture model. Its value is in the constraints it makes explicit: one codebase, explicit dependencies, environment based configuration, replaceable backing services, separated build and run stages, stateless processes, port binding, process based scaling, fast start and shutdown, environment parity, log streams, and one-off admin processes.
What still holds
The strongest parts of twelve-factor are still practical because they reduce hidden coupling. A service that stores configuration in the environment can move between deployments without a rebuild. A service that treats backing services as attached resources can swap a database, cache, queue, or SMTP provider by changing configuration rather than code. A service that writes logs to standard output leaves collection, retention, search, and alerting to the runtime platform.
The process model also still matters. Running the application as one or more stateless processes makes horizontal scaling simpler. State that must survive a process restart belongs in a backing service, not in local memory or the local filesystem. That does not mean every application has to be stateless in the business sense. It means runtime processes should be replaceable.
What needs revisiting
The original model predates much of the current platform stack. Containers, service meshes, managed identity, policy as code, progressive delivery, distributed tracing, and managed observability are now normal in many production systems. These do not invalidate twelve-factor. They add detail that the original factors do not cover.
The config factor needs extra care. Environment variables are useful for deployment specific values, but they are not a complete secrets management system. Sensitive values need controlled storage, rotation, access auditing, and least privilege. Environment variables can be part of the delivery mechanism, but the security property comes from the surrounding platform and operational process.
The backing services factor also needs precision. Treating databases, caches, and queues as attached resources is a good abstraction for deployability. It is not a licence to ignore data ownership, transaction boundaries, latency, consistency, recovery, or migration strategy. A database is not interchangeable in the same way as a log drain.
Build, release, and run
Separating build, release, and run is still one of the most useful deployment disciplines. The build stage turns the code repository into an immutable artefact. The release stage combines that artefact with configuration. The run stage executes the release. A release cannot be mutated once it is created, so any change produces a new release. This separation makes rollbacks, promotion between environments, and incident analysis easier because the exact artefact and configuration can be identified.
A common failure mode is rebuilding for each environment. That hides differences between staging and production inside build output. Prefer one artefact promoted through environments, with environment specific configuration applied at release or run time.
Disposability and shutdown
Fast startup and graceful shutdown are not cosmetic details. They affect deploy speed, autoscaling, crash recovery, and maintenance. A process should start quickly enough for the platform to replace failed capacity. It should also stop accepting new work during shutdown, finish or safely hand off in-flight work, and release leases or locks.
Background workers need the same treatment as HTTP servers. A worker that pulls a job from a queue and then exits without acknowledgement rules can lose work or duplicate work, depending on the broker and worker configuration. Shutdown behaviour should be tested, not assumed.
Dev, staging, and production parity
Parity reduces defects that only appear after deployment. It does not require every environment to have the same scale or cost profile. It means the same application artefact, the same dependency classes, similar configuration mechanisms, and similar operational paths.
A local database running in a container can be useful, but it is not equivalent to a managed production database with different extensions, isolation settings, backup behaviour, connection limits, and failure modes. The more a feature depends on platform behaviour, the more important it is to test that feature in an environment that resembles production.
What twelve-factor does not solve
Twelve-factor does not define service boundaries. It does not decide whether a system should be a monolith, modular monolith, or microservice architecture. It does not replace threat modelling, capacity planning, reliability engineering, schema design, data governance, or cost control.
It is best used as a deployability baseline. A system can satisfy twelve-factor and still be unreliable. It can also violate one factor deliberately for a sound reason. The important part is that the trade-off is explicit.
Practical checklist
Use the following checks during design and review.
Code and artefacts
There is one codebase per deployable service. Builds are repeatable. The same artefact is promoted through environments.
Configuration
Deployment specific values are outside the codebase. Secrets are handled by a controlled secrets mechanism. Configuration changes are reviewable and auditable.
Runtime
Processes are stateless where possible, start quickly, shut down cleanly, and expose health signals that match real readiness.
Operations
Logs are emitted as event streams. Admin tasks run with the same code and configuration model as the application. Development, staging, and production stay close enough to catch integration defects early.
Conclusion
The twelve-factor app is still useful when it is treated as a deployability checklist. Its limits are just as important as its rules. Use it to remove hidden deployment assumptions, then add the missing production concerns: security, observability, data ownership, resilience, and operational readiness.
