Twelve Factor app

Twelve Factor app

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 a SIGTERM signal and after a grace period if the container is not stopped docker sends a SIGKILL 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.