Best practices for building a deployable software-as-a-service app
Tags: microservices, 12factorapp, docker, saas
Published: 2020-07-08 20:15:16

---
title: Best practices for building a deployable software-as-a-service app
published: true
date: 2019-07-19 16:53:24 UTC
tags: microservices,12factorapp, docker,saas,
canonical_url: https://medium.com/rajdeep-dev/best-practices-for-building-a-deployable-software-as-a-service-app-4305f6058be9
---

#### The Twelve-Factor App, Quick Summary

In the modern era, the 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 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-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 Twelve Factors

**I. Codebase**

One codebase tracked in revision control, many deploys

> A twelve-factor app is always tracked in a version control system, such as [Git](http://git-scm.com/), [Mercurial](https://www.mercurial-scm.org/), or [Subversion](http://subversion.apache.org/). A copy of the revision tracking database is known as a _code repository_, often shortened to _code repo_ or just _repo_.

![](https://cdn-images-1.medium.com/max/443/1*YH_9MkWr11plDKU3nKcu9A.png)<figcaption>Single Code Base</figcaption>

There is always a one-to-one correlation between the codebase and the app:

- If there are multiple codebases, it’s not an app — it’s a distributed system. Each component in a distributed system is an app, and each can individually comply with twelve-factor.
- Multiple apps sharing the same code is a violation of twelve-factor. The solution here is to factor shared code into libraries which can be included through the [dependency manager](https://12factor.net/dependencies).

**II. Dependencies**

Explicitly declare and isolate dependencies

> Most programming languages offer a packaging system for distributing support libraries, such as [NPM](https://www.npmjs.com/) for Node.Js or [Rubygems](http://rubygems.org/) for Ruby. Libraries installed through a packaging system can be installed system-wide (known as “site packages”) or scoped into the directory containing the app (known as “vendoring” or “bundling”).

**A twelve-factor app never relies on the implicit existence of system-wide packages.** It declares all dependencies, completely and exactly, via a _dependency declaration_ manifest. Furthermore, it uses a _dependency isolation_ tool during execution to ensure that no implicit dependencies “leak in” from the surrounding system. The full and explicit dependency specification is applied uniformly to both production and development.

In Python there are two separate tools for these steps — [Pip](http://www.pip-installer.org/en/latest/) is used for declaration and [Virtualenv](http://www.virtualenv.org/en/latest/) for isolation. Even **C** has [**Autoconf**](http://www.gnu.org/s/autoconf/) for dependency declaration, and static linking can provide dependency isolation

#### III. Config

Store config in the environment

> An app’s _config_ is everything that is likely to vary between [deploys](https://12factor.net/codebase) (staging, production, developer environments, etc). This includes:

- Resource handles to the database, Memcached, and other [backing services](https://12factor.net/backing-services)
- Credentials to external services such as Amazon S3 or Twitter
- Per-deploy values such as the canonical hostname for the deploy

> Apps sometimes store config as **constants** in the code. This is a violation of twelve-factor, which requires the **strict separation of config from code**. Config varies substantially across deploys, the code does not.

A litmus test for whether an app has all config correctly factored out of the code is whether the codebase could be made open source at any moment, without compromising any credentials.

> **The twelve-factor app stores config in _environment variables_** (often shortened to _env vars_ or _env_).

#### IV. Backing services

Treat backing services as attached resources

> A _backing service_ is any service the app consumes over the network as part of its normal operation. Examples include datastores (such as [MySQL](http://dev.mysql.com/) or [CouchDB](http://couchdb.apache.org/)), messaging/queueing systems (such as [RabbitMQ](http://www.rabbitmq.com/) or [Beanstalkd](https://beanstalkd.github.io)), SMTP services for outbound email (such as [Postfix](http://www.postfix.org/)), and caching systems (such as [Memcached](http://memcached.org/)).

**The code for a twelve-factor app makes no distinction between local and third-party services**

![](https://cdn-images-1.medium.com/max/885/1*xz-DKX5C2NhS0nmkeorm4Q.jpeg)<figcaption>Attached resources</figcaption>

#### V. Build, release, run

Strictly separate build and run stages

A [codebase](https://12factor.net/codebase) is transformed into a (non-development) deploy through three stages:

- The _build stage_ is a transform which converts a code repo into an executable bundle known as a _build_. Using a version of the code at a commit specified by the deployment process, the build stage fetches vendors [dependencies](https://12factor.net/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](https://12factor.net/config). The resulting _release_ contains both the build and the config and is ready for immediate execution in the execution environment.
- The _run stage_ (also known as “runtime”) runs the app in the execution environment, by launching some set of the app’s [processes](https://12factor.net/processes) against a selected release.

**The twelve-factor app uses strict separation between the build, release, and run stages.** For example, it is impossible to make changes to the code at runtime, since there is no way to propagate those changes back to the build stage.

![](https://cdn-images-1.medium.com/max/580/1*Wea4WMn8y0Bh8gOrVy4Zgw.jpeg)<figcaption>Build PipeLine</figcaption>

#### VI. Processes

Execute the app as one or more stateless processes

> The app is executed in the execution environment as one or more _processes_.

In the simplest case, the code is a stand-alone script, the execution environment is a developer’s local laptop with an installed language runtime, and the process is launched via the command line (for example, python my\_script.py). On the other end of the spectrum, a production deploy of a sophisticated app may use many [process types, instantiated into zero or more running processes](https://12factor.net/concurrency).

**Twelve-factor processes are stateless and** [**share-nothing**](http://en.wikipedia.org/wiki/Shared_nothing_architecture) **.** Any data that needs to persist must be stored in a stateful [backing service](https://12factor.net/backing-services), typically a database.

#### VII. Port binding

Export services via port binding

Web apps are sometimes executed inside a webserver container. For example, PHP apps might run as a module inside [Apache HTTPD](http://httpd.apache.org/), or Java apps might run inside [Tomcat](http://tomcat.apache.org/).

> **The twelve-factor app is completely self-contained** and does not rely on runtime injection of a webserver into the execution environment to create a web-facing service. The web app **exports HTTP as a service by binding to a port** , and listening to requests coming in on that port.

In a local development environment, the developer visits a service URL like http://localhost:5000/ to access the service exported by their app. In deployment, a routing layer handles routing requests from a public-facing hostname to the port-bound web processes.

This is typically implemented by using [dependency declaration](https://12factor.net/dependencies) to add a web server library to the app, such as [Tornado](http://www.tornadoweb.org/) for Python, [Thin](http://code.macournoyer.com/thin/) for Ruby, or [Jetty](http://www.eclipse.org/jetty/) for Java and other JVM-based languages. This happens entirely in _userspace_, that is, within the app’s code. The contract with the execution environment is binding to a port to serve requests.

HTTP is not the only service that can be exported by port binding. Nearly any kind of server software can be run via a process binding to a port and awaiting incoming requests. Examples include [ejabberd](http://www.ejabberd.im/) (speaking [XMPP](http://xmpp.org/)), and [Redis](http://redis.io/) (speaking the [Redis protocol](http://redis.io/topics/protocol)).

Note also that the port-binding approach means that one app can become the [backing service](https://12factor.net/backing-services) for another app, by providing the URL to the backing app as a resource handle in the [config](https://12factor.net/config) for the consuming app.

#### VIII. Concurrency

Scale-out via the process model

> Any computer program, once run, is represented by one or more processes. Web apps have taken a variety of process-execution forms. For example, PHP processes run as child processes of Apache, started on demand as needed by request volume. Java processes take the opposite approach, with the JVM providing one massive uberprocess that reserves a large block of system resources (CPU and memory) on startup, with concurrency managed internally via threads. In both cases, the running process(es) are only minimally visible to the developers of the app.

**In the twelve-factor app, processes are a first-class citizen.** Processes in the twelve-factor app take strong cues from [the Unix process model for running service daemons](https://adam.herokuapp.com/past/2011/5/9/applying_the_unix_process_model_to_web_apps/).

Using this model, the developer can architect their app to handle diverse workloads by assigning each type of work to a _process type_. For example, HTTP requests may be handled by a web process, and long-running background tasks handled by a worker process.

#### IX. Disposability

Maximize robustness with fast startup and graceful shutdown

> **The twelve-factor app’s** [**processes**](https://12factor.net/processes) **are _disposable_, meaning they can be started or stopped at a moment’s notice.** This facilitates fast elastic scaling, rapid deployment of [code](https://12factor.net/codebase) or [config](https://12factor.net/config) changes, and robustness of production deploys.

- Processes should strive to **minimize startup time**
- Processes **shut down gracefully when they receive a** [**SIGTERM**](http://en.wikipedia.org/wiki/SIGTERM) signal from the process manager.

#### X. Dev/prod parity

Keep development, staging, and production as similar as possible

Historically, there have been substantial gaps between development (a developer making live edits to a local [deploy](https://12factor.net/codebase) of the app) and production (a running deploy of the app accessed by end-users). These gaps manifest in three areas:

- **The time gap** : A developer may work on code that takes days, weeks, or even months to go into production.
- **The personnel gap** : Developers write code, ops engineers deploy it.
- **The tools gap** : Developers may be using a stack like Nginx, SQLite, and OS X, while the production deploy uses Apache, MySQL, and Linux.

**The twelve-factor app is designed for** [**continuous deployment**](http://avc.com/2011/02/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.

![](https://cdn-images-1.medium.com/max/715/1*ixiOYZikACJMJ1qlicqWgA.jpeg)<figcaption>Summarizing the above into a table</figcaption>

[Backing services](https://12factor.net/backing-services), such as the app’s database, queueing system, or cache, is one area where dev/prod parity is important. Many languages offer libraries which simplify access to the backing service, including _adapters_ to different types of services. Some examples are in the table below.

![](https://cdn-images-1.medium.com/max/666/1*46p6dK8NWn6j0Ff-xBhLjA.jpeg)<figcaption>Libraries</figcaption>

**The twelve-factor developer resists the urge to use different backing services between development and production** , even when adapters theoretically abstract away any differences in backing services.

#### XI. Logs

Treat logs as event streams

_Logs_ provide visibility into the behavior of a running app. In server-based environments, they are commonly written to a file on disk (a “logfile”), but this is only an output format.

> **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.

In staging or production deploys, each process’ stream will be captured by the execution environment, collated together with all other streams from the app, and routed to one or more final destinations for viewing and long-term archival. These archival destinations are not visible to or configurable by the app and instead are completely managed by the execution environment. Open-source log routers (such as [Logplex](https://github.com/heroku/logplex) and [Fluentd](https://github.com/fluent/fluentd)) are available for this purpose.

#### XII. Admin processes

Run admin/management tasks as one-off processes

The [process formation](https://12factor.net/concurrency) is the array of processes that are used to do the app’s regular business (such as handling web requests) as it runs. Separately, developers will often wish to do one-off administrative or maintenance tasks for the app, such as:

- Running database migrations (e.g. manage.py migrate in Django, rake db:migrate in Rails).
- Running a console (also known as a [REPL](http://en.wikipedia.org/wiki/Read-eval-print_loop) shell) to run arbitrary code or inspect the app’s models against the live database. Most languages provide a REPL by running the interpreter without any arguments (e.g. python or perl) or in some cases have a separate command (e.g. irb for Ruby, rails console for Rails).
- Running one-time scripts committed into the app’s repo (e.g. php scripts/fix\_bad\_records.php).

> One-off admin processes should be run in an identical environment as the regular [long-running processes](https://12factor.net/processes) of the app. They run against a [release](https://12factor.net/build-release-run), using the same [codebase](https://12factor.net/codebase) and [config](https://12factor.net/config) as any process run against that release. Admin code must ship with application code to avoid synchronization issues.

The same [dependency isolation](https://12factor.net/dependencies) techniques should be used on all process types. For example, if the Ruby web process uses the command bundle exec thin start, then a database migration should use bundle exec rake db:migrate. Likewise, a Python program using Virtualenv should use the vendored bin/python for running both the Tornado web server and any manage.py admin processes.

#### Conclusion

These are the main idea of 12-factor app development. It really helps in a modern-day **microservice architecture.** microservices architecture should follow these 12-factor styles for better scaleability, rapid development without wasting too much time to roll out new features in production and make developer job easy.

You can learn more about it in details from the official 12-factor app website [https://12factor.net/](https://12factor.net/). Written by Adam Wiggins.

Thank You, Happy Reading.

* * *