“Good code fails when you don’t have a good process and a platform to help you. Good teams fail when you don’t have a good culture that embraces DevOps, microservices and not giant monoliths”, said Java Framework Spring’s Tim Spann when asked about the reason for choosing 12 factor apps.
If your enterprise team is often struggling with overly complicated, slowed-down app deployment, 12 factor app methodology should be the go to solution for you.
What are 12 Factor Apps?
A methodology or process created specifically for building Software as a Service (SaaS) apps, the 12 Factor Applications can help you avoid headaches typically associated with long term enterprise software projects.
Laid down by Heroku founder, these 12 design principles function as an outline to guide the development of a good architecture.
- They include defined practices around version control, environment configuration, isolated dependencies, executing apps as stateless resources and much more
- Work with a combination of backing services like database, queue, memory cache
- and, Utilize modern tools to build well structured and scalable cloud native applications
Interestingly however, they are not a recipe on how to design the full system, rather a set of prerequisites that can get your projects off to a great start. Here’s a look at the 12 factors
There should be only a single codebase per app, but multiple deployments are possible.
Multiple apps sharing the same code, violates the twelve-factor methodology. The solution is thus to factor the shared code into libraries which can be included through the dependency manager.
As for multiple deployments, it’s possible with the same codebase being active across them, although in different versions.
A 12-factor app relies on the explicit existence declaration of all dependencies, completely and exactly, via a dependency declaration manifest. And you must also use a dependency isolation tool along with dependency declaration.
- Dependency declaration is required as it simplifies setup for developers who are new to the app.
- Using dependency isolation tool during execution ensures that no implicit dependencies “leak in” from the surrounding system.
- And using both dependency declaration and dependency isolation together is important, because only one is not sufficient to satisfy twelve-factor.
Apps storing config as constants in the code is a violation of the 12-factor. Instead, config should be stored in environment variables (env vars). Why? Config varies substantially across deploys, whereas code does not. Env vars are on the other hand, easy to change between deploys without changing any code.
Secondly, these env vars are independently managed for each deploy. They are never grouped together as environments. And this model scales up smoothly as the app naturally expands into more deploys over its lifetime.
#4 Backing services
Under the 12-factor process, backing services are treated as attached resources, independent of whether they are locally managed or third party services. They can be accessed easily via a URL or other credentials, and even swapped one for the other.
The result? If your app’s database is misbehaving because of a hardware issue, you can simply spin up a new database server restored from a recent backup. The current production database could be detached, and the new database attached – all without any code changes.
#5 Build, release, run
There should be strict separation between the build, release and run stages. This is done to ensure that no changes can be made to the code at runtime, since there is no way to propagate those changes back to the build stage.
Why is this necessary? Because runtime execution (unlike builds) can happen automatically. Such as if there is a server reboot, or a crashed process being restarted by the process manager, these problems which are preventing the app from running could also cause the code to break. And that could be a major problem, particularly if no developers are on hand.
Twelve-factor processes are stateless and share-nothing. It is never assumed that anything cached in memory or on disk will be available on a future request or job. All the data compiling is done during the build stage, and everything that needs to persist is stored in a stateful backing service, typically a database.
#7 Port binding
A 12-factor app is completely self-contained, and does not rely on the runtime injection of a webserver into the execution environment to create a web-facing service. It always exports services via port binding, and listens to requests coming on that port.
Almost any kind of server software can be run via a process binding to a port, and awaiting incoming requests. Examples include HTTP, ejabberd, and Redis.
To ensure the scalability of your app, you should deploy more copies of your application (processes) rather than trying to make your application larger. The share-nothing, horizontally partitionable nature of twelve-factor app processes means that adding more concurrency is a simple and reliable operation.
To do this, the developer has to architect the 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.
The twelve-factor app’s processes are disposable, i.e.,
- Startup time is minimal
- Can shutdown gracefully at a moment’s notice
- Robust against sudden crashes or failure
All of this facilitates fast elastic scaling, rapid code deployment or config changes, as well as robustness of production deploys.
#10 Dev/prod parity
A 12-factor app is designed for continuous deployment by minimizing the sync gap between development and production. Here’s how:
- Time gap: reduced to hours
- Personnel gap: code authors and deployers are the same people
- Tools gap: using similar tools for development and production
Keeping development, staging and production as similar as possible will ensure anyone can understand and release it. This ensures great development with limited errors, and also enables better scalability.
Twelve-factor apps should not be concerned about routing and storage of it’s output stream or writing/managing log files. 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.
This factor is more about excellence than adequacy. While success is possible even without logs as event streams, the pay-off of doing this is significant.
#12 Admin processes
Apps should run admin/management tasks as one-off processes, in an identical environment as the regular long-running processes of the app. They run against a release, using the same codebase and config as any process run against that release. Admin code must ship with application code to avoid synchronization issues. And dependency isolation techniques should also be the same for all process types.
This factor is more from a managing your app point-of-view than developing services, but is still important.
The Underlying Benefits
Thus the 12-factor apps methodology helps create enterprise applications that:
- Use declarative formats for setup automation. This minimizes the 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, thus removing the need for servers and systems administration
- Limits differences between development and production, enabling continuous deployment for maximum agility
- Can scale up without any major changes to tooling, architecture, or development practices, hence performance is a priority
Should You use the 12 Factors?
You are now well aware of the 12 factor apps methodology, as well the advantages they bring. But is it always a great choice to make? Probably not.
If you are an enterprise with a development team that is still trying to overcome the baggage of your legacy, on-premise applications, 12 factor is not ready for you. The right use case would be for those new apps or instances where you’ve already started the refactoring process for a brownfield project that you’re completely reworking. Or when you are building new cloud-native applications, that's when you definitely need 12 factor apps.
It’s all about deciding what your main problem is and if this methodology can solve that problem. And of course, as always, you should prioritize what works for your team.
Our expert development teams at Srijan can help you understand your enterprise project requirements, and whether 12 factor apps can ensure a better app architecture. To know more, book a consultation.