Since the dawn of time (circa January 1st 1970), people have wanted software. In the early days, customers were willing to wait for their software, studiously loading floppy disks into their desktops or transcribing BASIC code from a magazine. But in these fast moving modern times with drones delivering groceries within the hour, customers don’t want to (and cannot afford to) wait around for their business critical applications to be deployed and configured. They want software now, and they probably want it in their web browser. This is the core appeal of software as a service (SaaS). But with that requirement of immediacy comes the challenge of delivering an increasingly complex infrastructure fast and consistently. Infrastructure as code (IaC) solves this problem.
Whether your application is architected in a single-tenant model where a whole stack of dedicated resources are deployed per customer, a multi-tenant model where customers share resources or a hybrid, there are gains to be had from defining your infrastructure as code. Tools such as Hashicorp Terraform, AWS CloudFormation or Pulumi can be used to blueprint your infrastructure in standardized blocks that can be deployed over and over.
Single-Tenant Applications Have The Most To Gain
When your application is single-tenant (in a “silo” isolation model), you have the most to gain from utilizing infrastructure as code in your onboarding process. When a customer comes to your website and likes what they see, you want them to be able to put in some credit card details and start using your software. What you don’t want is to have to schedule time with an engineer to do a rollout because your potential customer might find a competitor that solves their problem now.
By defining your application infrastructure as code you have a quick, repeatable process for bringing up a tenant which can be integrated into your onboarding process. When your infrastructure as code is managed by a service such as Terraform Cloud or AWS CloudFormation, then provisioning a whole new tenant can be just a few API calls away. With this in place, as soon as a tenant finishes initial sign up you can start provisioning their new infrastructure in the background. If done well, by the time they have finished your full onboarding flow their infrastructure is already there waiting for them, seamless.
Demo Faster Sell Quicker
Even in these days of immediate gratification there are still some customers who may be more cautious about buying software. Rather than jumping in with their credit card out, such customers may prefer a guided demo of the software before committing to a purchase. However, this doesn’t mean they have less appetite for speedy delivery, they just have more questions. By defining your infrastructure as code you can enable sales personnel to quickly and easily provision their own demo tenant without the input of any engineers. Services such as AWS Service Catalog can make the process of provisioning a new tenant a push button exercise. This will reduce sales cycle time and make for happier customers, sales people and engineers.
Tenancy Models Matter At Scale
When your application is architected in a multi-tenant way you probably have to worry less about provisioning infrastructure on initial sign up, instead you are likely going to want to manage scaling and sharding.
Sometimes there are external constraints on your system that can limit how wide your system can scale horizontally, perhaps it’s database resourcing, or maybe you are hitting an AWS per account service quota. These constraints limit how many tenants you can accommodate using a pure pooling model, where all infrastructure is shared across all tenants.
A common pattern to solve these problems is to shard your tenants by breaking them up into smaller groups that share resources. In the database example, this may be achieved at the resource level by creating a new database instance per shard while leaving all other resources shared across the whole app. In the AWS quota example, it may be easier to deploy an entirely new stack of shared resources in a new AWS account.
Either way, when adding new tenants to the system there will be a point where a new shard needs to be created. The new shard will require resources consistent with all existing shards, perhaps with some nominal differentiation. A perfect use case for parameterized infrastructure as code! At scale, you want this sharding process to be done preemptively as existing shards approach their capacity limits so that there is always room for new tenants to be onboarded. Monitoring capacity across shards is vital. With sufficient monitoring in place, the process for creating new shards and rebalancing tenants across underutilized shards may even be automated.
Many cloud based SaaS applications will start their lives hosted in a single geographic region. As the service grows and brings on more tenants, there may come a point where it becomes prudent to start deploying to multiple regions. You may wish to expand to more markets and reduce latency for those customers, or want to protect against a whole region outage. When you need to add a new operating region to your multi-tenant application, you will likely need to duplicate much of your existing infrastructure. If this infrastructure is defined in code this becomes a relatively simple task, allowing you to focus on how your application code may need to change to work in a globally distributed fashion.
There are still times when new infrastructure may need to be provisioned per customer, even if your application is otherwise multi-tenant. A simple example can be found with vanity domains (e.g. mycompany.yourapp.com). At a minimum, to accommodate vanity domains you will need a new DNS record and routing rule on your load balancer. By defining these through infrastructure as code you create a repeatable pattern which can be more easily modified en masse.
Single-Tenant in a Multi-Tenant World
Some people assume that a fully multi-tenant (“pooled”) architecture is the right way to run a SaaS system. While it is true that there are a number of benefits in architecting your solution to run in a multi-tenant way, there are still some instances where single-tenant deployments (also known as “silo” isolation) is a feature. In these cases, being able to provision a new copy of your entire infrastructure using infrastructure as code can turn potentially multi-month projects into mundane and speedy operations.
B2B SaaS companies will almost inevitably come across a potential customer who are willing to pay big money for their own dedicated instance of your software. Perhaps they need to keep their data within a country you don’t currently operate in or maybe they are a government agency which requires security guarantees a shared execution environment cannot provide. Whatever the reason, it is beneficial to be able to deploy an exact copy of your shared infrastructure for the dedicated use of a single tenant. Making effective use of infrastructure as code from the start allows that kind of flexibility, and may help unlock new markets.
On the other side of that coin, it can be beneficial for you as a platform operator to isolate tenants to their own set of infrastructure. You may have a key tenant, a so-called “noisy neighbour”, who due to comparatively enthusiastic use of your product is actually negatively affecting other customers’ performance. If you’re billing by usage, the last thing you want to do is to ask that key tenant to do less of it. You then have to choose: do you scale out beyond most tenants’ needs, implement rate limits and other measures within the application code, or do you rely on infrastructure-level isolation? Provisioning an isolated instance of your shared infrastructure for their exclusive use can eliminate any adverse effect on other customers, while allowing more fine-grained scaling of your platform for that key tenant’s needs. Once again, having infrastructure as code already in place for your entire stack greatly simplifies the implementation and migration process.
Better Faster Stronger
No matter how your product is architected, there are benefits to be gained from defining your infrastructure as code. Repeatable infrastructure means faster deployments, which aids customer onboarding, and can hopefully increase sales. This repeatability can also be leveraged to create systems which are simultaneously more resilient and more flexible.
This blog is written exclusively by The Scale Factory team. We do not accept external contributions.