top of page

The Twelve Factor App Part II

In this blog post, we will be building on what was covered in Part I where the first six principles of the framework was discussed. The last six are:

  1. Port binding

  2. Concurrency

  3. Disposability

  4. Dev/prod parity

  5. Logs

  6. Admin processes

Without further ado, let's dive right in.


  1. Port Binding

    "Export services via port binding" - This principle dictates that an application should be self-contained and runnable without the need to be injected into a web server at runtime. This means that the app should export it's own services via a port, and not depend on a separate web server (e.g Apache or Nginx). Instead, it should handle it's own HTTP requests by listening on a specific port.


  1. Concurrency

    "Scale out via the process model" - The concurrency principle is about making an application scalable by design. Rather than handling more load by scaling vertically (adding more CPUs and RAM) on a single server, a 12-Factor application is designed to scale horizontally. This means to add more machines to handle the load and run multiple identical processes on those different machines. If one of the processes or machine crashes, the others can continue to handle requests making the application more robust and fault-tolerant.

Figure 1.1 Vertical Scaling vs Horizontal Scaling
Figure 1.1 Vertical Scaling vs Horizontal Scaling
  1. Disposability

    "Maximise robustness with fast startup and graceful shutdown" - This focuses on making an application's processes disposable. What does this mean? Processes should have a minimal startup time which allows for rapid scaling. They should shut down gracefully when they receive a termination signal (e.g SIGTERM). This involves cleaning up resources, finishing any in-flight requests, and gracefully closing connections.


  1. Dev/Prod Parity

    "Keep development, staging, and production as similar as possible" - The goal is to minimise the "it works in my machine" problem. Keeping the different environments consistent helps streamline deployments as moving an application from Dev to Prod becomes a simple, repeatable operation. Reduce the gap between the environments by using the similar tools, configurations, and workflows.


  1. Logs

    "Treat logs as event streams" - Logs provide visibility into the behaviour of a running app by logging processes like port it's listening on, every requests it receives and also errors in code which can be used for troubleshooting. The application should not be responsible for managing, storing, or archiving it's own log files. 12-Factor apps should write logs to stdout in a structured JSON format that can be used by an agent to transfer to a centralised location (e.g ELK Stack and Splunk) for consolidation and analysis purposes.


  1. Admin Processes

    "Run admin/management tasks as one-off processes" - The last principle of the 12-Factor App methodology recommends that administrative tasks should be kept separate from the application processes. Any one-off periodic admin tasks, such ad DB migrations or server restarts should be run as a separate process or application. However, this should be run on identical systems as the app running in the production environment.


Does 12-Factor still matter today?

Although conceived over a decade ago, the 12-Factor framework matters in today's cloud-native and microservices-focused workloads:

Maintainability & Portability

By separating configurations from the codebase, you can deploy the same application to different environments (e.g staging and production) without changing the code. This makes the app easily portable between different cloud providers or deployment platforms. Additionally, explicitly declaring dependencies ensures the app's environment is self-contained and reproducible, preventing the "it works on my machine" problem.


Scalability & Resilience

The principle of running the app as one/more stateless processes means you can easily scale horizontally by simply adding more instances of the processes. This is a fundamental requirement for handling varying loads in a today's microservices environment. Concurrency and Disposability also contributes to this, allowing for rapid startups and graceful shutdown to meet demand, which is crucial for efficient resource utilisation in the cloud.


Continuous Delivery & DevOps

By strictly separating the build, release, and run stages, a reproducible deployment process can be created. This ensures that was is tested in staging gets deployed to production. The process minimises manual intervention and allows for automated, frequent, and reliable deployments. Dev/prod parity reduces the number of bugs/surprises that emerge when code moves from one environment to another.


Summary

In summary, the 12-Factor App isn't just a set of rigid rules; it's a foundational framework for building applications that are fit for the future. In a cloud-native, microservices-driven landscape, these factors are the bedrock of success. They enable teams to deploy with confidence, and to build a scalable system that can meet the demands of a fast-paced digital world.

Comments


bottom of page