The twelve factor methodology is a language and platform-agnostic set of design principles that can help to build portable, scalable, maintainable, compatible, and robust apps rapidly. It was started by the Heroku engineering team.
Reading - https://12factor.net/
As per the documentation -
The twelve-factor app is a methodology for building software-as-a-service apps that:
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, 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.
The Twelve Factors
1. Codebase
one codebase for an app tracked by version control where team members push the code.
microservices can have different codebases since they are essentially different apps.
within each codebase, we can have multiple deployments - dev/staging/test/prod envs.
2. Explicitly declare and isolate dependencies
twelve-factor app declares all the dependencies completely and exactly, via a dependency declaration manifest ex. requirements.txt, package.json files.
we can install app-related dependencies by creating virtual environments for the app to avoid interference from outside system dependencies. ex. node_modules, python venvs, etc.
docker containers help to run our apps in a self-contained environment that is isolated from the host system.
3. Config
An app’s config is everything likely to vary between deploys (staging, production, developer environments, etc). This includes:
Resource handles to the database, Memcached, and other backing services.
Credentials to external services such as Amazon S3 or Twitter.
Per-deploy values such as the canonical hostname for the deploy.
twelve-factor app stores configs of the app in env files that are different for different deployment environments.
4. Backing services
backing services are shared resources that are attached externally to twelve-factor apps.
examples include:
databases - MySQL, Postgres, Mongo, etc.
messaging/queueing systems - RabbitMQ, MQTT, Beanstalked, etc.
SMTP - postfix
caching systems - Redis, Memcached, etc.
5. Build, release, run
Strictly separate build, release, and run stages.
build stage - converts a code repo into an executable bundle known as a build(an executable file). The build stage fetches dependencies and compiles binaries, and assets.
release stage - build from the previous stage along with configs makes a release with a unique release version/timestamp/id. The release is ready to be executed immediately in the execution environment. Releases are append-only ledgers and a release cannot be mutated once it is created. Every small change in the codebase should create a new release. twelve-factor app allows rollbacks to previous releases.
run stage (aka runtime) - runs the app in an execution environment against the release.
6. Processes
Twelve-factor processes are stateless and share-nothing.
If the same app is running on multiple processes and any information that is needed to be shared across all processes should be stored in a stateful backing service, typically a database/cache.
The data stored on a process won’t be available across other apps running across other processes.
7. Port binding
All the services needed to be exported should be connected with ports.
The web app exports HTTP as a service by binding to a port, and listening to requests coming in on that port.
8. Concurrency
In the twelve-factor app, processes are first-class citizens.
Apps should scale out horizontally not vertically by running multiple instances of the app on different machines concurrently.
The app should be built keeping concurrency in mind.
9. Disposability
The twelve-factor app’s processes are disposable, meaning they can be started or stopped at a moment’s notice.
This facilitates fast elastic scaling, rapid deployment of code or config changes, and robustness of production deploys.
Processes should strive to minimize startup time.
codebase should not have any complex start scripts.
Processes shut down gracefully when they receive a SIGTERM signal from the process manager.
docker stop
sends aSIGTERM
signal and after a grace period if the container is not stopped docker sends aSIGKILL
signal to forcefully terminate the process running inside the container.During the grace period after
SIGTERM
signal, apps/processes can stop accepting new requests and complete current requests.The app should be able to handle
SIGTERM
signals to avoid any discrepancies.
10. Dev/Prod parity
Keep development, staging, and production as similar as possible.
The twelve factor app is designed for continuous deployment by keeping the gap between development and production small.
Possible gaps :
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 behaviour in production.
Make the tools gap small: keep development and production as similar as possible.
The twelve-factor developer resists the urge to use different backing services between development and production.
11. Logs
Treat logs as event streams.
Logs are the stream of aggregated, time-ordered events collected from the output streams of all running processes and backing services.
We can’t store logs on the containers as they get destroyed and recreated very often, so we can lose them.
Writing logs to a centralized backing service is also discouraged as it leads to tight coupling.
12. Admin processes
one-time admin operations involve running a migration, seeding a database, or resetting some database records.
All the one-time admin operations should be run on different processes but on an identical setup.