The Twelve-Factor Application design methodology
Nowadays, software is usually provided as a service, whether in the form of web applications or software as a service (SaaS). The Twelve-Factor App is an influential software application design model for designing a scalable application architecture.
Note
The Twelve-Factor App was published in 2011 by Adam Wiggins and provides a set of principles to follow in order to create code that can be released reliably, updated quickly, and maintained consistently.
The Twelve-Factor App methodology page can be found at https://12factor.net/. The following is a summary of the principles:
- Code base – “One code base tracked in revision control; many deploys”:
Each application must have its own code base (or repository); multiple applications should not share the same code. A code base is a repository of versioned code. However, we must avoid creating multiple code bases for different versions – version management must be managed by a repository tool such as Git. It is recommended that for all deployment environments, there should be only one repository, not multiple.
- Dependencies – “Explicitly declare and isolate dependencies”:
Every application has dependencies with other packages. Most of the dependencies require the use of external dependencies, and the objective is to deploy the application with its dependencies because they form a whole, a kind of bundle.
Therefore, you have to declare the dependencies explicitly and precisely before creation, and then isolate these dependencies at runtime.
This is enabled through NuGet tools in .NET Framework or npm for JavaScript. These tools define their dependencies inside the manifests, including very specific versions, and have the role of then ensuring that the dependencies are running correctly.
- Config – “Store config in the environment”:
The idea is to separate the code from the configuration of the application itself. This configuration can be placed in environment variables, which will be injected at runtime, and the configuration and the code will thus be in separate files. However, sensitive data such as credentials and keys should not appear visibly in the code, nor even in the configuration file, for security reasons. Good examples of external configuration files are the appsettings.json
file in .NET projects, a Kubernetes manifest file, and a docker-compose.yml
file.
- Backing services – “Treat backing services as attached resources”:
A support service is any service your application needs for its functionality, such as databases, mail servers, mail systems, caching systems, and even services running business functionality and security.
- Build, release, and run – “Strictly separate build and run stages”:
The build process focuses on building everything that is needed for your application, the release stage combines the output of the previous stage (the build stage) with the configuration values (both environmental and application-specific), and the run stage uses tools such as containers and processes to launch the application, meaning that it needs a specific environment to run the application that’s distinct from the environments used in the build and release stages.
- Processes – “Execute the app as one (or more) stateless process(es)” :
We are talking here about the process state. The application can work as a collection of stateless processes, implying that no trace of the state of another process (such as the state of the session) will be saved. Equally, the workflow and instances can be added and removed to handle a particular workload at a given time. A stateless process makes scaling easier. In conclusion, each process is independent of the others, which prevents surprises.
- Port binding – “Export services through port binding”:
An application is identified in the network by a port number or a domain name known to the Domain Name System (DNS). The idea behind the principle of port binding is that the use of ports in the network is very efficient – for example, port 80
is used for web servers running under HTTP, port 443
is the default port number for HTTPS, port 22
is for SSH, port 3306
is the default port for MySQL, and port 27017
is the default port for MongoDB.
- Concurrency – “Scale-out through the process model”:
The concurrency factor states that applications should be able to scale up or down elastically, depending on their workload.
- Disposability – “Maximize robustness with fast startup and graceful shutdown.”:
The availability principle states that applications should start and stop properly without slowness or errors. This means that users can access the application without experiencing service downtime issues.
In the event of a shutdown, it is recommended to ensure that all database connections and other network resources are properly terminated and that all shutdown activity is logged.
- Dev/prod parity – “Keep development, staging, and production as similar as possible”:
The dev/prod parity factor focuses on the importance of keeping the development, simulation, acceptance, and production environments as similar as possible. But why? Because it is important to identify potential bugs and errors during development and testing before an application is released to production, all deployment environments are similar but independent.
- Logs – “Treat logs as event streams”:
The logs factor highlights the importance of ensuring that your application doesn’t itself manage the routing, storage, or analysis of its output stream (i.e., logs).
For example, one consumer might be interested in error data, but another consumer is interested in request/response data. Yet another consumer is interested in storing all log data for event archiving. This means that logs should be treated as a stream of log events. If we remove an application, the log data persists long after.
- Admin processes – “Run admin/management tasks as one-off processes”:
This factor recommends not setting up one-time administration or management tasks in the application.
The examples given on https://12factor.net/ are for migrating databases and running one-time scripts to perform cleanup.
Now that we have discussed the Twelve-Factor App design methodology, let’s now move on to serverless applications.