This blog will explain the principles of the 12 factor app. These principle basically eliminate the unnecessary ache required while building your application. It makes the development process smooth, thus resulting in a robust and reliable application.
A twelve-factor app states that a single app should not have multiple codebases, otherwise it is a distributed system instead of an app. Also, multiple apps should not share the same code. It is include the common code in a separate library and add that library’s dependency in your code. This further eases the CI/CD pipelines as well.
This principle states that we should not depend upon implicit existence of system-wide packages. Instead, most of the developers follow the approach to isolate the dependency within a service by defining the multi-layer module dependency in a multi-module project. This is done to ensure that the conflicting libraries used in different services under a multi-module system(for instance) is avoided. There already exists tools to achieve this principle such as SBT, maven, gradle etc.
An application is usually deployed on different environments such as test, prod, qa etc. The configurations can vary from one environment to environment. So, an app must ensure that all the config is stored in separate environment file(s) which must be confidential as it may contain some confidential data such as password, database connection properties, third party service information etc.
4. Backing Services:
This principle states that any backing service apart from the main service should be treated as an attached resource. Some of the example of attached resources are database, amazon S3 etc. This should be done in such a way that they are accessed via config so that in case a change in third party services are required, it should not affect the actual service code. This also makes it easy to swap one backing service with another.
5. Build, release, run:
An application’s deployment process should go through three deployment stages to ensure that changes to the code cannot be made at runtime:
- Build stage: It is the stage where code repository is bundled into a versioned artifact where a build can be WAR, ZIP or JAR files.
- Release stage: As stated in principle 3, a separate config file should be maintained. So in this stage, the build should be combined with this config file containing data according to the environment on which it has to be released. Every release must have a unique release ID.
- Run stage: This stage will run the application against a selected release.
This principle states that the processes must be stateless and should share nothing. In case some data needs to be persisted, it must be stored in a separate backing service such as database. For example in a lagom application, the use of Akka persistence helps in persisting and recovering the state.
7. Port Binding:
This principle states that a twelve-factor app should always be an independent standalone service. If needed, should be available to other services via port binding so that the other services treat it as a resource which is then accessed using configuration (Principle 3) as a backing service (Principle 4).
The purpose of this principle is to make your application in such a way that it can handle workload and scaling them in cloud is smooth. This can be done by deploying additional copies of your application (process) instead of creating a large application. Each process running concurrently should be stateless thus achieving (Principle 6).
Building a disposable app means that the application should not take much time in order to start up and when goes down, it should result in a graceful shutdown. Fast startup of a process can be achieved by opting a micro-service architecture. This helps in smooth scaling and deployment of the application. Similarly, a graceful shut down should free up all the resources, any unfinished task should be returned back to the queue. Thus, leaving the system in an accurate state.
10. Dev/Prod Parity:
The development and production environment should be keep as similar as possible. This goes beyond the configuration. A large difference can lead to unintentional compatibility issues. Thus things such as backing services, database tools used should be similar.
An application can run successfully without logs, but this principle is extremely useful when you face some issues with your application such as events created in the past can be accessed with the logs which are usually helpful in debugging process. In such situations, logs help in order to debug the issue and resolve it. It further helps in providing the visibility of the behavior your application. Some of the logging frameworks available are SLF4J, Logback etc.
12. Admin Processes:
This states that the administrative tasks should run separate from the rest of the application as one-off processes. Such tasks include migrating a database. These tasks should usually be done during before the start of the application.
An application developed following a 12 factor app usually has low probability of failures and even if issues occurred, it provides a smooth way to tackle that problem.