An app’s foundation impacts its performance. This beginner’s guide to the 12 factor methodology covers everything about this app building framework.
Building a successful application doesn’t just come down to what you’re building. How you build it greatly influences its performance, efficiency, and longevity. Without a solid foundation, the app may not fully deliver on what you set out for it to do.
This is where the 12 factor app methodology comes in. This set of principles behind building apps aims to help developers design something that is scalable, reliable, and easy to maintain. Think of it as a framework that aids in developing a sturdy architecture for your app.
In fact, this methodology is something that we require all apps to pass at Divio. It’s even something that we can guide you through whilst you embark on the app development process.
In this article, we’ll be going through exactly what the 12 factor methodology is, step by step. We’ll be defining key terms, and explaining how the steps benefit your app. This guide is written for those who are new to this framework and anyone who’d like to refresh their knowledge before embarking on a new app development project.
Here’s what we’ll be covering:
What is the 12 Factor Methodology?
How to Decide if It’s Right For Your Project
Benefits of 12 Factor Methodology
The 12 factor methodology is a framework used to build software-as-a-service (SaaS) applications. These are software applications that are typically hosted on cloud platforms. These applications can then be accessed by clients. You might also see these types of apps be referred to as software-on-demand.
The 12 factor methodology was originally published in 2011/12 by Heroku programmers and was intended to be used for those deploying SaaS applications on their platform. However, it’s been adopted beyond this initial intention.
As previously mentioned, the 12 step method is a framework for building these types of applications. You might see the steps being referred to as practises, rules, or principles. They ensure that applications are reliable, quick, portable, and easily scalable. Essentially, it’s building with the long-term in mind. Think of it as a checklist before deploying a new application.
Let’s now take a closer look at each step.
The codebase is the source code that is used to build an application. It’s stored in a source code repository, and changes are tracked using a version control system, such as Git, Mercurial, or Subversion. The repository can also include scripts and configuration settings.
The 12 factor methodology stipulates that an application should only have one codebase. For distributed systems that are comprised of multiple interacting applications, each app has its own codebase that adheres to the 12 factor methodology. Whenever applications need to share code, it should be factored into libraries that can be reused across applications. This approach makes things cost effective and quicker to deploy. You’re not relying on duplicating multiple codebases with minor changes - this can get quite difficult to keep on top of.
However, multiple deployments from this single codebase can be made too. When this happens, the codebase remains the same - it just gets used for different requirements. It should be noted that there’s only a violation of the methodology if multiple codebases are present in a single app. Or, if the codebase is shared with another app.
Dependencies are the requirements needed to run an application. The 12 factor methodology states that these dependencies are always to be declared. This can be done in what is called a manifest file. This includes all the details of a dependency, including its correct versions, its name, whether it’s an external package, and so on.
According to the 12 factor methodology, dependencies should also be isolated during program execution. This is meant to provide a completely clean environment for an application to run in, so that system libraries don’t leak in and affect the runtime. This is often achieved using virtual environments, such as the “virtualenv” tool in Python or the virtual environment manager bundled with Anaconda.
Dependency declaration and isolation are important because it shouldn’t be assumed that it’s obvious that dependencies exist. This can mean that key dependencies go undetected, and can mean that applications don’t run as they should. It also stipulates that information about dependencies is not stored in the source code. This is because source code does not function like dependencies do. They’re completely different, and therefore should be kept separate to help maintain clarity.
Before we go further into this step, it’s important to determine what ‘config’ in this instance means. Rather than referring to an application’s internal configurations, this use of config refers to something else. Config here is based on how its configuration information is used within the application.
The 12 step methodology notes that configuration information should be kept separate in the application. This is because it can change significantly based on different environmental variables. Like dependency data, it’s very different to the rest of the application. Keeping it separate keeps the system clear and easier to manage.
Config details should be brought in at the deployment level. The reason behind this is that it makes deployments, and scalability, much easier. As a config doesn’t rely on any application logic, it can be tailored to different deployments.
Backing services are additional resources required by an app to run normally. They are normally additional services accessed over a network. A lot of these services can be third-party, such as Amazon S3 or MySQL. Other examples include email servers and databases. The 12 factor approach specifies that all of these should be managed as attached resources. All backing services are treated equally, regardless of whether they are in-house or third-party. One should be able to swap out backing services without altering application code.
Being treated as an attached resource means that, like config information, deployments are quicker and performance is more efficient. They’re not reliant on the codebase, which makes them much more flexible in how they work alongside deployments. Ultimately, it simplifies things.
Build, release, run is a set of stages that is used to deploy an application. They are also used to achieve these specific goals:
Build - converts the code in the code repository into an executable bundle that includes dependencies.
Release - combines the build with config settings.
Run - Runs the app in a suitable runtime environment by launching processes from a release.
The separation of these stages is important to maintain. Unless separated, these stages risk code break. It also means that if there are issues in any stage, it’s far quicker to make fixes. The separation of these stages also makes the whole system being developed far less complex.
A process is a running instance of an application. The 12 step methodology requires processes to be stateless and share-nothing. This means that no data should be stored within the application process. Instead, it should be stored to a backing service, like a database. It also means that there are no references made to previous executions or other running processes. Separate processes do not interact with, or keep track of, each other. Nothing is shared, and any additional data required for executions should be stored in a backing service. Basically, every time an application is fired up, it’s like it’s being started for the first time.
The reason behind this is that it makes the application more stable and easier to scale, as it improves latency. As the application doesn’t have any dependency on the server (as nothing is stored in it), it’s much easier to add and remove instances that can fluctuate with changes in traffic. In essence, they’re just a lot less complex.
Port binding relates to how an application is not identified by its domain name and IP address, but rather its port number. Any web service binds to a specific port number and listens for incoming requests on this port. The 12 step framework stipulates that this approach is far more reliable - domain names and IP addresses can be manually altered, and less easy to manage. The short of it is that port binding means that networking is less likely to go awry. It also makes it easy for apps to become backing services for one another, by specifying their port numbers within their config files.
Concurrency in this instance has everything to do with scaling. This step in the 12 factor methodology relates to how processes should be organized when they’re running simultaneously (or concurrently). It remarks that processes should be separated based on what they do (known as a process type). Different types of work are assigned to different process types. This makes scaling an application much easier as it means that the problem of scaling an app is reduced to adding additional processes of a specific type. This type of system enables horizontal scaling across machines and results in the app not being weighed down and getting slower. The selection of process types, along with the number of processes associated to each type, is referred to as the process formation.
Disposability in this case has to do with an app starting up and shutting down. The 12 factor framework specifies that disposability can increase the robustness of an application. Robustness relates to how applications handle errors and unexpected changes—think crashes, failures, and so on. Disposability, or developing application processes that can be started or stopped at any time, means that systems can recover far more quickly from errors or anything going a bit pear shaped. It also comments on how fast start ups and graceful shutdowns (shutting down processes, and database connections, safely) aid in the robustness of an application. Basically, if a system starts and stops as it should, it’s more likely to cope better with any problems it encounters.
The development/ product parity step in the 12 factor method relates to keeping certain environments similar, yet separate to each other. Gaps between dev and prod environments can arise due to differences in time, personnel, and tools. Maximizing parity between dev and prod environments allows code to be written and deployed rapidly, allows devs to be involved in deployment of their code, and ensures tools are used consistently across environments. This helps to simplify processes and also reduces the risk of bugs.
Logs are files that record the actions and behavior of an application and its processes. The 12 step methodology notes that logs should be treated the same as event streams. The idea here is to keep on top of your logs, continuously analyze the data coming through, and be reactive to them. It’s all about getting really familiar with your application, and getting to know it from the inside out.
In this instance, it’s less about the management of the logs, but rather about being proactive to the data that they’re providing. The routing of the logs, and the processing of their data should therefore be independent of each other. Logs should be stored separately from the application. The benefit of this approach is that problems can be caught earlier on, with solutions that are easier to deliver.
This step goes beyond app development. Admin processes are key in application management, and should be factored into the app before it’s released. Think of the ability to do database migrations, and so on. The 12 step framework requires one-off instances of these processes to be easily accessible and able to run in identical environments to the actual apps. This approach means that these processes shouldn't be executed by any other parts of your application. This will ensure that any changes made are easy to do, as well as not interfering with other processes in your app.
You can determine if the 12 factor methodology is right for your project by taking time to understand the needs of your team, the issues that they’re facing, and the application itself. Having a solid foundation to build an application on is never a bad idea, but you may find yourself tailoring this particular framework to your requirements. Resources, especially time and cost, may impact how quickly you’re able to get a project using this framework done - especially if you’re doing it retroactively.
You don’t need to switch it all up all at once, particularly if your application is already built. Rather, you can take it step by step, and prioritize what features are the most important and will have the biggest impact.
The 12 factor methodology is particularly suitable for large applications that have a lot of moving parts. Common use cases include:
Cloud hosted applications
However, it doesn’t stop there. This is a flexible framework that can be used in a variety of different projects. It’s one of the many benefits of the methodology. Let’s take a look at some more.
Having a foundational basis for building apps doesn’t just benefit the app itself - it extends to the team working on it. Here are some benefits that the 12 factor methodology brings.
The 12 step framework makes collaborative work on an app far more simple. Dependencies are clearly defined, there’s a single code base, and other key aspects of the app are easily accessible. A defined and clear architecture also makes it easier for new - and third party - developers to start working on the project.
Having a solid framework to build all applications saves time and other valuable resources in the long term. A standardized approach to building apps means apps can be built more quickly, and efficiently, without sacrificing quality and performance.
12 factor apps have increased elasticity, and can handle scaling without it notably changing the application architecture. This makes cost management a lot easier. The modular approach that the 12 step framework takes also means that components are far more flexible too.
The 12 factor methodology is a robust framework to build SaaS applications with. Using this standardized approach to creating apps has both short and long term benefits. Notably, it can drive down costs, improve performance and efficiency, and make collaborative working a whole lot easier. These are some of the many reasons why Divio requires applications we work with to pass the 12 factor methodology.