Applying the 12 Factor App Methodology

analytical dashboard
System Design Methods

Let’s begin with the first principle of the 12 factor apps.

In this article, we’ll apply the 12 factor app methodology to our serverless app running on AWS. By following this strategy, we’ll produce a powerful, robust system that will meet all the criteria required for designing modern applications that run on the cloud using industry best practices and system-design principles. Our goal is to create a solution with a hands-on approach taking somewhat abstract ideas and applying these to our system. We’ll begin with creating a trending application. The application should be able to take a configurable topic and begin studying it daily to understand its relevance based on the number of searches, website traffic hits and interests. The idea is that our application can learn insights and recommend to us information we may find useful or helpful.

I. Codebase

If we are running release cycles on quarterly, monthly, weekly or even daily, this challenges complexity grows at length. We need a way to have granular visibility at the file level and make sure that the changes we introduce are release version worthy. This helps us avoid introducing accidental unfinished features or inadvertently introduce defects to our production site. It also allows us a way to recover any version at any point in time. Using a codebase gives us this capability. By using a codebase we can ensure that our system can be built with any given revision, branch, tag or release we define. This means that if our local environments become unusable or unrecoverable, we can leverage our codebase and view this as our single source of truth. Doing this positions the developers to deliver a consistent product, the same way on every single delivery. Let’s apply the serverless method in combination with this approach. Serverless applications are simply that, we run our system on managed containers that remove the need for system administration. In other words, we get out of the business of managing servers. This will help us with some of the other principles but more on that later. Serverless systems typically are composed of many different components which are treated as bits and pieces that work together through common communication. Let’s use Github as our source control system. This will be the solution we’ll use to store our code. It’s an example of the first principle… the codebase!

Defining Our Codebase

Since we have many different micro-services, front-ends, etc., how can we apply a single codebase principle to something like this? Well, it’s important not to get too caught up on the wording and understand the concept. Each service, front-end, etc., should have a codebase, a single source of truth. They should collectively belong to the same project and we should be able to apply the above principles to each codebase. We should be able to logically group these together in some fashion (more on this later). By building our project, we implicitly build the application, and it represents our single source of truth, revision controlled and managed entirely as a collective representation of the applications state. We should never have two places where the same code resides. How can we logically determine what describes our codebase? We want the ability to have revision control. This means we should set up consistent branches and tags across our repositories to enforce deploying specific versions of our system. Doing this creates repos which will all follow the same naming, branching and tagging conventions. We also need the ability to deploy our entire system, but have the flexibility to source control each component within the system. You might be asking yourself, why not use the mono-repo approach? While Github has been the industry leader for many years, it does have its drawbacks, one of which is having sub-level projects. Are there solutions to this problem? Sure, you can use submodules. You could also do scripting to overcome the obstacle. Each of these have additional considerations and if you have the man-power and expertise then don’t let this opinion stop you. For us, we want to keep it simple. Another reason for avoiding mono-repos for system-wide code is that some build tools are not well equipped to deal with building folder level projects, again, mostly because of the limitations of Github. With this perspective and what we’ve learned so far, let’s consider what it would take to define a codebase for our trending application.

A. Front-End

We know that we’ll have a user interface which lends itself to what we refer to as a front-end. This is a good logical separation between different components of our system. Typically, front-end design considerations are different from back-end systems. Front-ends are concerned with real-estate, responsive behavior and presentation of data.

B. Back-End

On the other hand, system data is the primary consideration for the back-end. Back-ends are typically concerned with gathering information being requested in a responsive manner. Responsive, though, in this context refers to speed and ability rather than screen rendering. Back-end services are usually involved with persisting information or retrieving that information from a datastore of some kind. Therefore, this is another logical separation.

C. Analytic System

We need a system to study the daily habits of the web. This system would be responsible for reviewing information that is trending for the given topic that we are interested in. This implies reading data and crunching the numbers. Since we want our system to be efficient, we want to separate our analytical system from the back-end api. Logically, they are two different components since they’re primary responsibilities are not the same. Analytical systems' are mostly concerned with computations of the data they are ingesting. Typically, they perform some type of aggregation or simply store the data as-is in the form of data lakes to later be analyzed or processed.

D. Infrastructure

Finally, we want to leverage the capability of the cloud. In this scenario, we’re talking AWS which implies AWS SAM or AWS CDK. Applying the 12 factor principles, we also want to version control our infrastructure. Version controlling our infrastructure allows us to roll out the precise infrastructure and its configuration at any point in time. This gives us full control of our environment and also allows us to recover from any disaster that could potentially occur that would damage our systems initial or current state. In summary, we’ll have the following repos:

  • Front-end Interface
  • Back-end API
  • Offline Analytics System
  • Infrastructure
  • Creating A Brand

    Now that we’ve conceptually considered the logical separation of the components which will make up our system, let’s give it a name. Using a synonym tool, we use the word “trend” and discover “drift”. Our application will be called Drifter. We can define our repositories under a logical grouping or common project called Drifter. A sample list of repositories:

    Example Codebase

    Each name conveys the intent of the repository. And with that, we acheive readability and intent with our naming.

    In the next article, we'll look at how we can apply the second principle Dependencies into our system-design.