Designing or developing any cloud-based application is not a simple straightforward process and always involve a number of intricate steps right from managing codebases, injecting library dependencies, configuring system properties and leading into a proper production deployment at scale. This is considered to be as one of the most difficult stages to manage while building any cloud-based app. In order to properly build and manage these cloud-native apps, a number of identified patterns have been introduced with a design methodology. Before we move deep down further on cloud migration and how to build native apps, let us first understand the 12 Factor App design methodology, written by Heroku co-founder Adam Wiggins.
What is 12 Factor App Design Methodology?
It is a design methodology which has been introduced to manage cloud-based or software as a Service (SaaS) apps. Some of the key features or applications of this design methodology are as follows:
- Use declarative formats for setup automation, to minimize time and cost for new developers joining the project
- Have a clean contract with the underlying operating system, offering maximum portability between execution environments
- Are suitable for deployment on modern cloud platforms (Google cloud, Heroku, AWS etc..), obviating the need for servers and systems administration
- Minimize divergence between development and production, enabling continuous deployment for maximum agility and can scale up without significant changes to tooling, architecture, or development practices
If we simplify this term further, 12 Factor App design methodology is nothing but a collection of 12 factors which act as building blocks for deploying or developing an app in the cloud. Listed below are the 12 Factors:
- Codebase: A 12 Factor App is always tracked in a version control system such as Git or Apache Subversion (SVN) in the form of code repository. This will essentially help you to build your code on top of one codebase, fully backed up with many deployments and revision control. As there is a one to one relationship between a 12 factor app and the codebase repository, so in case of multiple repositories, there is always a need to consider this relationship as a distributed system consisting of multiple 12 factored apps. Deployments should be automatic, so everything can run in different environments without work.
- Dependencies: As the app is standalone and needs to install dependencies, it is important to explicitly declare and isolate dependencies. Moreover, it is always recommended to keep your development, production and QA identical to 12 Factor apps. This will help you to build applications in order to scale web and other such applications that do not have any room for error. As a solution to this, you can use a dependency isolation tool such as ex VirtualEnv for Python uniformly to remove several explicit dependency specifications to both production and development phases and environments.
- Config: This factor manages the configuration information for the app. Here you store your configuration files in the environment. This factor focuses on how you store your data - the database Uniform Resource Identifier (URI) will be different in development, QA and production.
- Backing Services: This includes backing service management services (local database service or any third party service) which depends on over a network connection. In case of a 12 factor app, the interface to connect these services should be defined in a standard way. You need to treat backing services like attached resources because you may want different databases depending on which team you are working with. Sometimes developers will want a lot of logs, while QA will want less. With this method, even each developer can have their own config file.
- Build, Run, Release: It is important to run separately all the build and run stages making sure everything has the right libraries. For this, you can make use of required automation and tools to generate build and release packages with proper tags. This is further backed up by running the app in the execution environment while using proper release management tools like Capistrano for ensuring timely rollback.
- Stateless Processes: This factor is about making sure the app is executed in the execution environment as one or more processes. In other words, you want to make sure that all your data is stored in a backing store, which gives you the right to scale out anything and do what you need to do. During stateless processes, you do not want to have a state that you need to pass along as you scale up and out.
- Port Binding: Twelve factor apps are self-contained and do not rely on runtime injection of a web server into the execution environment to create a web-facing service. With the help of port binding, you can directly access your app via a port to know if it's your app or any other point in the stack that is not working properly.
- Concurrency: This factor looks into the best practices for scaling the app. These practices are used to manage each process in the app independently i.e. start/stop, clone to different machines etc. The factor also deals with breaking your app into much smaller pieces and then look for services out there that you either have to write or can consume.
- Disposability: Your app might have different multiple processes handling different tasks. So, the ninth factor looks into the robustness of the app with fast startup and shutdown methods. Disposability is about making sure your app can startup and takes down fast and can handle any crash anytime. You can use some high quality robust queuing backend (Beanstalk, RabbitMQ etc.) that would help return unfinished jobs back to the queue in the case of a failure.
- Dev/Prod Parity: Development, staging and production should be as similar as possible. In case of continuous deployment, you need to have continuous integration based on matching environments to limit deviation and errors. Some of the features of keeping the gap between development and production small are as follows:
- Make the time gap small: a developer may write code and have it deployed hours or even just minutes later.
- Make the personnel gap small: developers who wrote code are closely involved in deploying it and watching its behavior in production.
- Make the tools gap small: keep development and production as similar as possible.
- Logs: Logging mechanisms are critical for debugging. Having proper logging mechanisms allows you to output the log info as a continuous stream rather than managing the entire database of log files. Then, depending on the configuration, you can decide where that log will publish.
- Admin Processes: One-off admin processes help in collecting data from the running application. In order to avoid any synchronization issues, you need to ensure that all these processes are a part of all deploys.
Conclusion: Factor 12 is a DevOps Services's methodology which is mainly used for new apps or instances where you have already started the refactoring process. It would help build a cloud application system with a strong architecture at the core which is reliable and easier to manage.