12 Factor App

A quick outline of 12 Factor Apps

Fernando Villalba
4 min readJul 6, 2019

The 12 Factor App was drafted by Heroku, describing how applications should be designed to run on their platform and it has quickly become an excellent reference of good practice microservice design and great model to follow when you start designing your own. Below I will define each factor and see how well we are doing this ourselves. I will also add some links for further information.

A 12 factor app aims to:

  • Use declarative formats for setup automation, this is more deterministic than imperative formats.
  • Maximum portability between execution environments
  • Be suitable for deployment on modern cloud platforms.
  • Minimise divergence between development and production, enabling continuous deployment agility.
  • Scale up without significant changes to tooling, architecture, or development practices.

1. Codebase

One codebase tracked in revision control, many deploys

  • It must always be in source control.
  • Multiple apps should not be in the same codebase, instead dependencies should be libraries.
  • Same codebase across all deploys!

2. Dependencies

Explicitly declare and isolate dependencies

  • All dependencies must be declared and included in the app ecosystem, separated from the host.
  • Dependency declaration and isolation must always be used together, only one or the other is not enough.
  • Everything should run with a deterministic build command of some kind.
  • Do not rely on the implicit existence of systems tools.

3. Config

Store config in the environment

  • Config should be strictly separated from code, not as constants in the code. This does not include internal application config that will not vary between deploys.
  • Configuration should be passed as environment variables, so it can be separated from the application and reduced the chance that it will be added to source control.
  • Avoid grouping env vars into categories as these can spin out of control, such as dev, production, etc. Keep config separate from code.
  • Configuration that doesn’t change much between environments should be defaulted to its usual value.

4. Backing Services

Treat backing services as attached resources

  • Treat backing services (such as databases) as attached resources, this means that you should be able to swap them without the need to change the code.

5. Build, release, run

Strictly separate build and run stages:

The build stage fetches vendors dependencies and compiles binaries and assets.

The release stage takes the build produced by the build stage and combines it with the deploy’s current config

The run stage (also known as “runtime”) runs the app in the execution environment

Keep in mind these:

  • A release cannot be mutated once it is created, only reverted to a previous version.
  • Releases should have unique IDs
  • Builds should be under developer supervision whereas runtime should be designed so someone else can manage it and easily understand it.

6. Processes

Execute the app as one or more stateless processes

  • Twelve factor processes are stateless and share nothing with other processes/instance of microservice — any data that needs to persist is stored in a stateful backing service, typically a database.
  • Memory space or filesystem of the process can be used as a brief, single-transaction cache. Never assume this will be available for a future request.
  • Sticky sessions must never be used, instead use something like redis or memcached.

7. Port binding

Export services via port binding

  • The twelve-factor app is completely self-contained and must export HTTP as a service by binding to a port and listening to requests there.

8. Concurrency

Scale out via the process model

  • We should have different process types for different workloads, for example one to receive a user request and another one to process it. This makes scaling easier.
  • They can scale to cover your distributed resources
  • Apps should never daemonize or write PID files, this should be managed by an init process.
  • One app, multiple process types for different jobs.

9. Disposability

Maximize robustness with fast startup and graceful shutdown

  • Minimise startup time.
  • Processes shutdown gracefully when they receive SIGTERM
  • Processes should be robust against sudden death, use a robust queueing backend.
  • Even better — design crash only software

10. Dev/prod parity

Keep development, staging, and production as similar as possible

  • 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.
  • Don’t use lightweight backing service replacements for local and development environments to avoid surprises.

11. Logs

Treat logs as event streams

Everything goes to stdout and gets collected and collated by something like Stackdriver or Cloudwatch.

12. Admin Processes

Run admin/management tasks as one-off processes

Any one-off admin processes should be run against a release and using the same codebase and (ideally) config running against that release.

Some Shortcomings of 12 Factor App

The 12 factor app is a phenomenal start with Microservices and your operations team will love you for this. However this model falls short in some areas:

  • It doesn’t define how you should do effective microservices logging. Sending it to output and collecting it with an aggregate is great, but there is more to it.
  • Doesn’t talk about how to make microservices observable, like monitoring, tracing and metrics.
  • It doesn’t mention good testing practices such as unit testing and contract testing. Your coders may still demand integrated environments left and right — which is not the aim of microservices.
  • It doesn’t define how to logically arrange your microservice architecture, like should you use Domain Driven Development? Etc.

Regardless of these I feel that the 12 factor app is the best way to start designing microservices and any developer who works with them must read and understand it, just not stop there.

Additional Resources

https://12factor.net/

https://youtu.be/GZ4sAEUMOnM

--

--

No responses yet