In this blog post, we are going to introduce 12 factor application. Writing of application codes predates most of the cloud solutions lots of application programmers are used to nowadays so in order to write modern applications in a declarative way using clean contracts that is deployed in cloud platforms, there is a methodology that we have to follow called 12 factor application. Here, I have attempted to do a high level summary of what those principles are.
Principle I. Codebase
“One codebase tracked in revision control, many deploys”
Your code base should have an easy to understand and logical version control system. Every deployment should have its own code repository that can be deployed to multiple environments. Avoid housing multiple applications into the same repository as it makes version control almost impossible to understand and makes all the version entangled leading to non value added work.
Principle II. Dependencies
“Explicitly declare and isolate dependencies”.
Never rely on implicit existence of system-wide packages. This includes not just making sure that the application-specific libraries are available, but also not counting on, say, shelling out to the operating system and assuming system libraries such as curl or ImageMagick will be there as there is no guarantee that they will exist on all systems where the app may run in the future. In python for example, declaration and isolation can be achieved by using Pip and Virtualenv respectively. In order to satisfy this principle, both declaration of dependency and isolation must always be used together. Management of dependencies should be done within the application and not from an external source. These dependencies should be hosted in a repository within the app
A 12 factor app must be self-contained. That includes making sure that the application is isolated enough that it’s not affected by conflicting libraries that might be installed on the host machine.
Principle III. Config
“Store config in the environment”.
The idea behind this principle is that an application should be completely independent from its configuration as storing of configs as constant in a code should be fully avoided. Configs should have a separate file of their own and not hosted within the code repository. Having a separate config file makes it easy to update the config values without touching the actual code base. This eliminates the need for re-deployment of your applications when you change certain values in your config files. In other words, configs belong in the environment as variables, not in the application, you should be able to move it to another environment without having to touch the source code. Some developers achieve this goal by creating configuration files of some sort, specifying details such as directories, hostnames, and database credentials. Instead, 12 factor apps store their configurations as environment variables; these are, as the manifesto says, “unlikely to be checked into the repository by accident”, and they’re language and operating system independent.
Principle IV. Backing services
“Treat backing services as attached resources”.
In a 12 Factor app, any services that are not part of the core application, such as databases, external storage, or message queues, should be accessed as a service — via an HTTP or similar request — and specified in the configuration, so that the source of the service can be changed without affecting the core code of the application. For example, if your application uses a message queuing system, you should be able to change from RabbitMQ to ZeroMQ (or ActiveMQ or even something else) without having to change anything but configuration information. In this case, each service is treated as a resource.
Principle V. Build, release, run
“Strictly separate build and run stages”.
We’ve already said that the application needs to be stored in source control, then built with all of its dependencies. That’s your build process. We talked about separating out the configuration information, so that’s what needs to be combined with the build to make a release stage that is ready to be ran in the run stage. It is also important that every release should have its own unique ID. A true 12 factor app must be strict about separating these three stages.
Principle VI. Processes
“Execute the app as one or more stateless processes”.
Any data that needs to persist must be stored in a stateful backing service, like databases. The idea is that the process is stateless and shares absolutely nothing. Many developers are used to
“sticky” sessions, storing information in the session with the confidence that the next request will
come to the same server, this goes against the 12 factor app methodology.
Principle VII. Port binding Principle
“Export services via port binding”.
In an environment where we’re assuming that different functionalities are handled by different processes, it’s easy to make the connection that these functionalities should be available via a protocol such as HTTP, so it’s common for applications to be run behind web servers such as Apache or Tomcat. Twelve-factor apps, however, should not be depend on an additional application in that way; remember, every function should be in its own process, isolated from everything else. Instead, the 12 Factor App manifesto recommends adding a web server library or something similar to the app itself, so that the app can await requests on a defined port, whether it’s using HTTP or another protocol.
Principle VIII. Concurrency
“Scale out via the process model”.
When you’re writing a twelve-factor app, make sure that you’re designing it to be scaled out. Applications should be built in such a way where scaling of applications in the cloud is seamless. By developing the app to be concurrent, new instances can be spun up in the cloud effortlessly. That means that in order to add more capacity, you should be able to add more instances rather than more memory or CPU to the machine on which the app is running. Note that this specifically means being able to start additional processes on additional machines.
Principle IX. Disposability
“Maximize robustness with fast startup and graceful shutdown”.
The idea that processes should be disposable means that at any time, an application can die and the user won’t be affected, either because there are others to take its place, because it’ll start right up again, or both. Building disposability in the app makes sure that when the app shuts down it does so in a graceful manner. It should be able to clean up all the resources it was utilizing, hence shut-down gracefully without any problems. Likewise, when it comes back up again, it does so very fast. Likewise, it means that when processes terminate, they should be able to finish their current request and refuse any incoming request and exit.
Principle X. Dev/prod parity
“Keep development, staging, and production as similar as possible”.
Deployed applications to Dev and Prod should have parity. In essence, there should only be a slight difference between both deployments. Vast difference in both may lead to unintended compatibility issues between dev and production code. It is reccomended that when building 12 factor app, backing services should not be different between dev and prod. Difference in backing services could cause issues down the road.
Principle XI. Logs
“Treat logs as event streams”.
Unlike monolithic and traditional apps that store log information in a file, this 12 factor principle directs that logs should be streamed to stdout and not just dumped into a log file.
Since logs do not always reside in the same place in cloud based environment after every burn because when new processes are started or when the application crashes, the logs will not be on a single machine or host; It is distributed among several cloud machines. Hence, the logs should be streamed into a common place. This might be as simple as redirecting stdout to a file, but in most cases it involves using a log router such as Fluentd and saving the logs to Hadoop or a service such as Splunk.
Principle XII. Admin processes
“Run admin/management tasks as one-off processes”.
This principle involves separating admin tasks such as migrating a database or inspecting records from the rest of the application. Even though they’re separate, however, they must still be run in the same environment and against the same base code and configuration as the application, and their code must be shipped alongside the application to prevent drift.
These postings are my own and do not necessarily represent BMC's position, strategies, or opinion.
See an error or have a suggestion? Please let us know by emailing email@example.com.