What is the 12 factor methodology?
The 12 Factor Methodology is a set of best practices for building modern, scalable, and maintainable web applications. It was created by engineers at Heroku and has become a widely accepted framework for developing cloud-native applications.
Let’s delve into each factor to uncover how they collectively contribute to a more efficient and effective development process.
1 – Codebase
One codebase tracked in revision control, many deploys
A codebase refers to the singular, version-controlled repository containing all the source code, configuration files, and assets that constitute a specific application.
A deploy is a running instance of the app. This is typically a production site, one or more staging sites, and instances running on developers local environment.
A centralized codebase promotes collaboration among developers while facilitates code reviews, automated testing, and quality assurance processes. It ensures that changes are thoroughly reviewed and tested before being integrated into the main codebase.
2 – Dependencies
Explicitly declare and isolate dependencies
In modern software development, applications often rely on various libraries, frameworks, and external services to function.
The dependencies factor suggests that these dependencies should be explicitly declared and isolated from the application code. This ensures consistent and reproducible builds, as well as predictable behavior across different environments.
3 – Config
Store config in the environment
Configuration refers to any information that can vary between different deployments of an application, such as database credentials, API keys, and environment-specific settings.
The config factor suggests that this configuration should be stored in the environment rather than being hard-coded into the application code.
Keeping configuration separate from the code ensures a clear separation of concerns. Developers can focus on writing code, while operations teams can manage and update configurations without needing to modify the codebase.
Also, it reduces the risk of exposing sensitive information in version control or other public places.
4 – Backing services
Treat backing services as attached resources
Backing services are external resources that your application relies on to function properly. These can include databases, file storage, third-party APIs, message brokers, and more.
The backing services factor suggests that your application should treat these services as external and attach them as resources, rather than bundling them directly into the codebase.
This factor supports the scalability and resilience of your application. You can scale different components independently and recover from service failures more effectively, switching to different service providers or technologies without rewriting your application code.
5 – Build, release, run
Strictly separate build and run stages
This factor advocates for distinct separation and management of different stages in the application’s lifecycle: building the code, releasing it to different environments, and running it in those environments.
The build stage involves compiling the code, resolving dependencies, and generating any necessary assets. It produces a deployable artifact that can be promoted through different environments.
The release stage takes the build artifact and combines it with the specific configuration for the target environment. This includes setting environment variables, database connections, and other runtime configuration details.
The run stage involves executing the application in the intended environment, whether it’s a development, testing, staging, or production environment.
6 – Processes
Execute the app as one or more stateless processes
The processes factor advocates for running the application as separate, stateless processes. Each process should be designed to be disposable, meaning it can start up quickly and be shut down gracefully without losing critical data or state.
Applications should avoid storing critical data or state within individual process instances. Instead, any state should be stored externally, such as in a database, cache, or distributed storage system.
7 – Port binding
Export services via port binding
The port binding factor suggests that your application should export its services by binding to a specific port. This means that your application should be self-contained and have its own web server to handle incoming requests.
8 – Concurrency
Scale out via the process model
The concurrency factor suggests that applications should be able to handle increased loads by running multiple stateless processes in parallel, rather than relying on larger, more complex individual processes.
To handle increased demand, you should add more instances of your application (horizontal scaling) rather than trying to scale up a single instance (vertical scaling).
9 – Disposability
Maximize robustness with fast startup and graceful shutdown
The disposability factor suggests that your application should be designed to start up rapidly and shut down gracefully. This enables seamless scaling, fault tolerance, and efficient resource usage.
10 – Dev/prod parity
Keep development, staging, and production as similar as possible
The dev/prod parity factor suggests that your development and production environments should be kept as similar as possible. This ensures consistency, reduces unexpected issues, and facilitates smoother deployments.
It minimizes the chances of “it works on my machine” issues and other discrepancies that can arise due to environment differences.
11 – Logs
Treat logs as event streams
The logs factor suggests that your application should generate logs as a continuous stream of events, capturing information about its behavior, errors, and important events.
Logs should be:
- Structured and well-formatted, making it easier to search, filter, and analyze them for troubleshooting and monitoring.
- Treated as event streams that provide a real-time record of the application’s activities. This can help diagnose issues, monitor performance, and track user behavior.
- Stored externally, rather than within the application. This ensures that logs are accessible even if the application experiences issues or crashes.
Also, avoid logging excessive or redundant information, as it can make logs difficult to parse and analyze. Focus on logging relevant and actionable data.
12 – Admin processes
Run admin/management tasks as one-off processes
The admin processes factor suggests that administrative and management tasks should be executed as distinct, standalone processes, rather than being tightly integrated into the application codebase.
Administrative tasks, such as database migrations, backups, and data imports, should be isolated from the main application code. This separation prevents these tasks from affecting the core functionality of the application.
Also, admin processes should be designed to be idempotent, meaning they can be safely run multiple times without causing unintended side effects.
Why is the 12 factor methodology becoming so popular?
The growing popularity of the 12 Factor Methodology is deeply tied to its seamless integration with microservices architecture. By emphasizing stateless processes, dynamic scalability, and modular development, it aligns perfectly with the needs of modern distributed systems.
This methodology has found favor among industry giants like Netflix, which applies its principles to optimize the scalability, resilience, and maintainability of their streaming services. Similarly, Heroku, the platform that originated the 12 Factor approach, employs these principles to empower developers in creating cloud-native applications.
As microservices continue to dominate software design, the 12 Factor Methodology stands out as a guiding framework that enables companies to efficiently build and manage their services while reaping the benefits of enhanced agility and streamlined deployment.