In the modern era, software is commonly delivered as a service: called web apps, or software-as-a-service. The twelve-factor app is a methodology for building software-as-a-service apps that:
- Use declarative formats for setup automation, to minimise 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-factor methodology can be applied to apps written in any programming language, and which use any combination of backing services (database, queue, memory cache, etc).
The 12 factors
1. Codebase – Code Repo or Repo: Use a version control system & there should only one code base(all deploy should happen from this repo only – dev/prod/..). If you have to make it multiple repos, follow the rule 2.
2. Dependencies: Explicitly declare and isolate dependencies.
- Bundler for Ruby offers the Gemfile manifest format for dependency declaration and bundle exec for dependency isolation.
- In Python there are two separate tools for these steps – Pip is used for declaration and Virtualenv for isolation.
- Even C has Autoconf for dependency declaration, and static linking can provide dependency isolation.
3. Config: Store config in different Environment
Types of Configs
- Resource handlers details to all backend services
- Credentials to systems
- Deployment variables
Key things on configs
- Use config file not tracked in Version Control.
- Using env-variables is also an option compared to saving to git
- As much possible, declare config specific to user & env
App should be scalable easily with less confusion. Do config management accordingly.
4. Backing Services: Always treat your backing services only as attached resources
- Config backing services – as such they should be replaceable without any code changes.
5. Build, release & run: Use CI/CD Setup.
- Build stage: Code repo is transformed into an executable bundle known as build. Also all dependencies are fetched & compiles binaries and assets.
- Release stage: Take build & adds config. This makes it a readily executable app.
- Run stage: Runs in application process
12factor rule: These 3 stages should be independent to each other.
6. Processes: Execute the app as one or more stateless processes **[Application Architect]**
Twelve-factor processes are stateless and share-nothing. Any data that needs to persist must be stored in a stateful backing service, typically a database.
If a data is must, include it to code repo or dependencies and it should be present by build stage.
7. Port binding: Export services via port binding **[Application Architect]**
- Mainly for Web App & Backend Apps. Ports are important for these apps to be easily accessible but given an environment they be have already consumed. Use config to declare what port to be used.
8. Concurrency: Scale out via the process model **[Application Architect]**
9. Disposability: Maximize robustness with fast startup and graceful shutdown **[Application Architect]**
- All processes should be disposable(stopped/restarted) at anytime.
- Short startup times.
- Graceful exits, any pending jobs – finish them and exit.
- [Crash-only software: More than meets the eye](https://lwn.net/Articles/191059/
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. Looking at the three gaps described above:
- 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.
The twelve-factor developer resists the urge to use different backing services between development and production. For example dont do – using SQLite locally and PostgreSQL in production for easy of installation & experimentations.
Also have strict version control. Specify the Version and isolate the problem. ==>> Make more portable
Learn more @ https://12factor.net/dev-prod-parity
11. Logs – Treat logs as events stream.
A twelve-factor app never concerns itself with routing or storage of its output stream. It should not attempt to write to or manage logfiles. Instead, each running process writes its event stream, unbuffered, to stdout. During local development, the developer will view this stream in the foreground of their terminal to observe the app’s behavior.
12. Admin processes
Run admin/management tasks as one-off processes. Under one, keep all you admin/maintenance jobs like database migrations, config reloading or restarts.
The driving principles for these 12 Factor App are:
1. One can easily recreate and start the app from scratch.
(I. Codebase; III. Config; V. Build, release, run; X. Dev/prod parity)
2. One should gracefully kill your app.
(VI. Processes; IX. Disposability)
3.One should gracefully scale your app.
(VI. Processes; VIII. Concurrency; XI. Logs; XII. Admin processes)
4. Technical plumbing is based on cloud assumptions.
(III. Config; IV. Backing services; VII. Port Binding; XI. Logs)