Introduction #
An explanation of the principles of twelve-factor apps, a methodology designed for modern applications and microservices, enabling better maintainability, scalability and continuous deployment.
Codebase #
One codebase per application, tracked in version control.
Principle #
Each application must have a single codebase versioned in a repository, even if it is deployed to several environments. This ensures code consistency across environments.
Version control #
Using version control systems (e.g. Git) lets you maintain application versions and easily track changes.
Benefits #
Improves traceability, collaboration and version management for teams, especially in an agile environment.
Dependencies #
Explicitly declare and isolate the application's dependencies.
Explicit declaration #
Specify all the application's dependencies in a configuration file (such as requirements.txt for Python or package.json for Node.js) to make installation and maintenance easier.
Dependency isolation #
Use isolated environments for each application (e.g. virtualenv in Python, Docker containers) to avoid dependency conflicts between projects.
Config #
Externalize configuration to separate code from environment settings.
Environment variables #
Use environment variables to store application configuration such as API keys, database URLs, etc. This avoids exposing sensitive information in the code.
Flexibility and security #
Per-environment configuration lets you deploy the same codebase to different environments (dev, prod) without changing the code.
Backing services #
Treat external services (databases, queues) as attached resources.
Interchangeable resources #
External services must be easy to replace without changing the code, only the configuration. This makes migrating to new solutions easier.
Portability #
By using services defined in external configuration, it becomes easy to move the application to other environments or providers.
Build, release, run #
Separate the build, release and run stages for better deployment management.
Build stage #
The build stage compiles the code and bundles all dependencies, producing a deployable version of the application.
Release stage #
Combines the build with specific configuration and records this version as ready for deployment. Each release must be immutable and identifiable (e.g. by a version number or a tag).
Run stage #
The stage where the code runs in the production environment. This separation improves version management and makes rollbacks easier when needed.
Processes #
Run the application as stateless processes to favor scalability.
State in services #
Processes must not keep state; they must use external services (such as a database) to store application state.
Horizontal scalability #
Stateless processes make it easy to add or remove instances, increasing capacity without affecting data consistency.
Port binding #
The application must be self-contained and exposed through a specific port.
Communication over the network #
The application must be reachable directly through a port, making deployment easier in environments such as Docker or Kubernetes.
Service flexibility #
Lets you combine different services in the same environment by assigning each one a specific port.
Concurrency #
Optimize the application to run with several concurrent processes.
Horizontal process model #
Use independent processes that scale in parallel, making it easier to handle variable workloads.
Multiprocessing #
Adopt parallel processing models to maximize resource usage.
Disposability #
Make processes fast to start and stop.
Fast startup #
Processes must start quickly to respond to fluctuating workloads.
Graceful shutdown #
When stopped, processes must shut down in a controlled way to avoid data corruption.
Dev/prod parity #
Keep development, staging and production environments as similar as possible.
Environment parity #
Avoid differences between environments to minimize the risk of errors during deployments.
Better testing #
Configuration parity improves test reliability by ensuring that what is tested in development will work in production.
Logs #
Logs are an event stream to centralize for effective analysis.
Continuous stream #
Logs must be treated as a continuous event stream, collected and centralized, without being written locally to the file system.
Centralization #
Sending logs to a centralized service makes it easier to monitor and troubleshoot applications in production.
Admin processes #
Administrative tasks are run as one-off processes.
One-off processes #
Run maintenance or administration tasks as isolated processes, e.g. using one-off scripts for database migrations or one-time jobs.
Security and stability #
One-off processes avoid interfering with running code and ensure application stability.
