If you haven't heard of the twelve-factor app, it gives us a recommendation or a methodology for developing SaaS or web apps structured into twelve items. The recommendation has some connections with microservice architecture and cloud-native environments which become more popular today. We can learn the details on its website. In this post, we will do a quick review of the twelve points.
One Codebase Multiple Deployment
We should maintain only one codebase for our application even though the application may be deployed into multiple environments like development, staging, and production. Having multiple codebases will lead to any kinds of complicated issues.
Explicitly State Dependencies
All the dependencies for running our application should be stated in the project itself. Many programming languages have a kind of file that maintains a list of the dependencies like package.json
in Node.js. We should also be aware of the dependencies related to the platform that runs our application like tools that are installed globally in the operating system.
The recommendation is to avoid the use of global scope dependencies at all. We can run our application in an isolated or virtual environment. This also prevents other processes in the system from affecting our application in some ways.
Maintain Configuration in The Environment
Maintaining configuration in the environment where our application running helps us to easily maintain the structure of the configuration of our application in multiple deployments. Keeping all configurations for all environments in a variable is discouraged because that just adds complexity. We can just populate a configuration for an environment into a variable in our code in which the value can be retrieved from a variable or secret manager in our CI/CD platform.
Attachable Backing Services
Any backing services for our application like databases or queue servers should be easily attached or detached so that we can swiftly switch or replace the service, for example, from a local database to cloud-based services. It is also related to the principle of multiple deployments where backing service can vary.
Separate Code, Build, and Run
This part means we shouldn't modify the released version of our application on the fly like for quick patching of an issue. Every release is read-only, we should modify the code in the development phase and release a new version.
Stateless Processes
This is the solution for an easy scaling out of our application. If our application is stateful which means certain values like sessions are tied to the runner engine or the machine, that will hinder us from scaling out with ease.
Binding Service to Port
We should allow our application to be accessed through a certain URL with a specific port. This dispels the need for a web server to expose the services of our application.
Concurrent Processes
We can categorize jobs in our application into several types. Then, the jobs can be implemented as modules that can run concurently to each other. This will help us to scale up only certain modules that are necessary.
Fast Startup and Graceful Termination
Our application should be able to be started within seconds and maintain termination well so that there is no job or data lost, especially in a microservice environment with several concurrent workers. Applying a mechanism like create before destroy in the deployment life-cycle can be helpful.
Similarity of Environments in Development Phases
Even though there are various adapters for anything, maintaining the similarity of technology or backing services in all environments is preferable. With an adapter, we can make MySQL and PostgreSQL interchangeable but there must be trade-offs and the absence of some features. Besides the technological aspects, gaps in people/teams or development processes should be managed too. We may leverage more container-based services to let the development environment have similar technology to the production environment.
Logs as Stream of Events
We don't need to make our application to manage its logs itself. Let our application expose a stream of events unbuffered into stdout or using third-party tools that are specified to manage and analyze logs.
Administration Tasks as One-Off Processes
Administration tasks like validating data or migrating databases should be implemented as one-off processes. This can be run using the same platform that we use for developing our main application. Most platforms today support REPL implementation where we can create a script and run it directly in a terminal session.
Comments
Post a Comment