12-Factor App #1: Why Serverless Version Control Is Critical
Stackery sponsored this post.
The principles described in The Twelve-Factor App have come to guide most modern development and operations, whether or not they were directly influenced by it. Apps aligned with the 12-factor principles should be more reliable and much easier to maintain and present a clearer path for new developers and team transitions.
This series, of which this is the first part, will explore each of those 12 principles and how your serverless app can best serve them. We’ll cover a variety of tools beyond Amazon Web Services (AWS) that serve as AWS alternatives or that enhance the AWS process.
These articles are written with the beginner in mind, but hopefully, even the experienced code cowgirl steeped in DevOps should find some useful information.
Principle 1: Your Codebase Should Be Managed by Version Control.
This principle is occasionally misinterpreted as “use Git” but there are two errors there:
- There are more options than git and GitHub;
- There are ways to use any kind of version control that don’t really conform to this design principle.
Options Beyond GitHub
There are more tools to manage your code than git, such as Mercurial or Subversion. And if you decide to use git, you don’t have to use GitHub. GitHub is one possible service for your storing the code and revision tracking information for your application (your code repository’ or just “repo”). You could run a local git server, and most enterprises that used version control did this until 2005 or so — many still do! Behind the frontrunner GitHub, GitLab is the next most popular option, but AWS also has CodeCommit to let you store your code in the same place as the rest of your serverless stack.
No particular implementation of the version control tooling breaks this design principle. Even if your repo isn’t stored anywhere but a virtual version control server on your own laptop, you’re still tracking changes. For serverless, it makes very little sense to use a private bare-metal server for your version control when everything else will be in a highly managed cloud environment.
Using CodeCommit from AWS makes deploying changes to your Lambdas slightly easier, or if you want to automatically integrate git with your serverless stack a bit more closely, here’s an article on grabbing notifications from GitHub (‘webhooks’) with a simple serverless stack.
It’s Codebase, Not Codebases: Defining an App
The code that makes your app work needs to be stored in a single repository. Wait, what’s an app? Are we talking about phones all of a sudden? There’s been some overloading of the term “app” to mean either:
- A mobile “app” as a way to generally access the web instead of using a phone’s browser;
- Some kind of running code on a server.
We’re pointing to the second term and it’s clearly a pretty vague idea. Is a machine-learning algorithm that sorts shopping results an app? What about the database service? But we started with these questions talking about codebases and codebases can help us with this definition. An app is a single-running code repository.
If you rely on running the code from two different code repositories, you have two apps! If these services are very, very tightly linked and can’t run without each other on the same server, there’s a chance you’re not really following 12-Factor and you should consider moving all of that code into a single app.
One Codebase per App: Shouldn’t We Reuse Code?
Multiple apps using the same codebase are also not following 12-Factor. If you have a whole separate node Lambda that does long-running tasks and doesn’t communicate with your other function, and you shove that into the same code repository, your repository is now responsible for several unrelated services and has some key vulnerabilities as a result.
If a blob of code is getting reused by multiple other codebases, you should treat it the same way you do your apps other dependencies and package it up as a library. If you need help encapsulating a single serverless function’s code for use on multiple other stacks, that’s a great application for the Stackery toolkit.
Why Is This Principle Critical?
Imagine this: You give one of your developers access to the code repo, they push up a few changes for their day one commit, the next morning a whole separate team is bleary-eyed because the new dev accidentally broke their service by changing the package versions their code relied on. The stuff of developer nightmares — or at least exhaustion and annoyance!
I Have Three Apps: ‘Production, Staging, and Dev’
This confusion is understandable! When we re-use code on our staging server and production server, aren’t those two separate apps? Not quite, those are two deployments (some people will say ‘deploy’ though I don’t really care for that).
- From 12factor.net
This makes more sense in light of principle 3: Store Config in the Environment and 10: Dev/Prod should be as similar as possible. The codebase should not change or mutate between these multiple environments.
Special Problems in Serverless
Serverless has the potential to violate this principle in special ways. You have fundamentally violated this principle if your process of making your first AWS Lambda serverless function is going to the Lambda dashboard, adding some code in the Lambda UI and deploying. The code for that Lambda is now stored (from the perspective of the developers on your team) solely within the AWS interface, and there is zero connection with your version control system!
Later principles reveal this with greater clarity, regarding the handling of configuration and storage. This problem can extend beyond Lambda code, and generally be described as “critical pieces of your app are stored somewhere in a configuration UI and must be replicated manically along with your codebase to replicate the app.”
This problem is not one that the good people at AWS are unfamiliar with, and they have a plethora of solutions. Lambdas can be configured to use code directly from your version-controlled repository, and more generally AWS CloudFormation has the capacity to store all your configuration as code.
Outside of AWS this requirement has been pursued as the “infrastructure as code.”
How Stackery Can Help
When you first enter Stackery, you see an easily-manipulated canvas that lets you drag in and connect serverless functions to storage, Cognito, and API gateways, etc. Best of all, you can deploy all of it to AWS with the touch of a button. It’s an easy, fun way to get your first serverless app up and running.
But before you create your first stack, Stackery’s UI asks you to designate a code repository. All that pretty, graphic tooling is actually stored as code in a repository you control. Stackery creates templates for your application stack using the Serverless Application Model (SAM).
While serverless can push you to use a more replicable, streamlined 12-factor process, tooling and planning are key to make sure your serverless app isn’t causing more dev friction than your old platform. Stackery will continue to work to make this process easier, and future articles will explore more of these 12 design principles and how you can align from the outset.
Read the second article in this series on serverless dependencies and configuration.
Feature image via Pixabay.