How To Design Applications For Cloud (SaaS)
Software as a Service (SaaS) has been a predominant model for many software vendors. It helps similarly delivering software as a Cloud vendor delivers infrastructure services. SaaS applications are often deployed on a public cloud, like Amazon Cloud (AWS), Microsoft Azure, Google Cloud and so on. However, at times the organization may choose to use their datacenter (a.k.a. private cloud) to host the SaaS application and leverage their investment in the infrastructure. When you are designing SaaS applications, it takes more than just deploying application bits to the Cloud. Taking proper design considerations can not only help you in accomplishing a good design, but it can also help you in reducing costs and manage your deployment more effectively. In this post, I will cover some key considerations and tips to design SaaS applications that I have found useful over the years.
How Is Designing Applications For Cloud Different From On-premise Applications Design?
That’s a valid question that many Architects face, especially in the early phases. There are certain subtle differences. Let’s look at some of these just to get the perspective.
- Better Modularization: If you have a monolithic application with a huge footprint, it is perhaps wise to see if it can be broken into logical components that can be deployed separately. This not only improves modularity but helps you reduce the footprint of the application. Let’s say you have an application that uses background jobs to refresh data. You could segregate the core application and the background jobs as 2 (or more) components that can be deployed separately. This will reduce the footprint of the core application. So, you could potentially choose a smaller resource size. Also, depending on the needs, you can scale these two independently. So, if there is an increase in demand for background jobs, you can increase its capacity and likewise for the application tier. Since the resource size for each of these is small, scaling only the required tier/component will lead to an overall lower cost than more bulky resources for the monolith. Makes sense?
- Application is always up-to-date: This is a big shift for many on-premise applications. In the Cloud, customers typically expect the application to be always on the latest version. Now, if you think about it as an Architect it means you are not only able to update the application bits but also upgrade customer data with preferably no customer involvement. That is, it is completely transparent to them.
These are just some of the differences. But, you get the point.
Key Design Considerations for SaaS
When you are designing an application for Cloud, you want to consider the following key points.
- Choose appropriate Cloud services: Of course, you are deploying to Cloud. But, which services do you want to use? Are you simply going to use Infrastructure as a Service (IaaS)? Or are you going to take advantage of some Platform as a Service (PaaS) capabilities as well? The answer may not be always straightforward. So, here are some guidelines.
- Are you going to have the same application deployed to multiple Cloud platforms or on-premise as well? In that case, it may make sense to not have (or minimize) Cloud vendor-specific services and stick to more of IaaS services.
- Cost should be an important consideration in choosing the services. For example, certain PaaS services that are Cloud vendor managed may be managed by your team itself to reduce cost. While this may not make sense for every service, it is worth exploring.
- Keep your team expertise in mind. What would it take to use a certain Cloud service? And, if the team were to also maintain the underlying infrastructure, what skills would be needed?
- Design for failure: Designing fault-tolerant and highly available applications is fundamental to Cloud. Assume that your application will run into issues and how you will ensure that it continues to serve the users. These could be application failures or underlying infrastructure failures. There are a few useful capabilities offered by Cloud vendors to help here.
- Use a Load Balancer: You can put the application nodes behind a Load Balancer for both load-balancing purposes as well as to make sure that even if one or more nodes go down, the application is served via the other nodes.
- Geographically distributed application: Several Cloud vendors offer capabilities to spread the application across multiple geographical areas so that even if one area is impacted (say, due to a natural disaster), the application can be served from the other areas. For example, AWS supports deploying an application across multiple Availability Zones.
- Modularize your application: As we discussed in the earlier section, segregating components that can be deployed and managed separately can help reduce the footprint of the application and thus reduce the cost of the infrastructure. You may also consider making some of these components as microservices. The microservice approach can be particularly useful if there are other potential consumers besides your application. Now, that does not mean, you go overboard and create unnecessary components. Hence, one way to do this is to make components that can be deployed separately (such as core application versus background jobs).
- Security: Security involves many aspects – from securing your infrastructure to application. Some of the key aspects include ensuring that only the required ports are opened, using as minimal privileges on the resources as possible, having proper role-based access control, use of encryption, and so on. Security should not be looked at as a one-time deal. It is an on-going process that should improve and evolve over time.
- Multi-tenancy: A key benefit of running in the Cloud is being able to serve multiple customers using the same instance of the application. This brings out some obvious challenges in the application design to ensure that each customer’s data is segregated for both security and regulatory purposes. Some teams choose to go with a different persistent storage instance per customer, such as a separate database per customer. And, some choose to segregate data using row-level identifiers. Regardless of which approach you take, it is important to ensure that the architecture meets the scalability and security needs. For example, if you choose to go with a database per customer, you can host multiple databases on one RDS instance. And, when you run out of capacity, you can stand up another RDS instance.
- Zero/Minimal Downtime and Seamless Upgrades: Believe it or not, many customers expect that SaaS applications will have zero or very minimal downtime and since these are often managed by the same company who built the application, it should be upgraded seamlessly. The challenge is your application may not have been designed to handle upgrades smoothly, especially if it is a pre-existing application being converted to a SaaS application. There are 2 key aspects to consider a) deploying application bits and files b) handling persistent store upgrades. For rolling out application bits strategies like Blue/Green deployment can be used in which the new release is deployed to a new stack, tested and made live if the rollout was successful. The older stack resources can be decommissioned and reclaimed at a later point. One approach to achieve seamless upgrades is to make the underlying data model n – 1 compatible. What that means is if the release being deployed is of data model version n, it’s data model is backward compatible with the previous data model version (n – 1) thus ensuring that the upgrade will not break it. How can you ensure that? This requires incorporating discipline throughout your development cycle and following certain guidelines, like not deleting any columns, providing necessary upgrade scripts to handle any data migration needs, and so on. And, in the event upgrade is not successful, having support to rollback the upgrade. Now, you can understand this is not only technically challenging as this involves data migration and rollback, but it could also lead to a significantly slower rollout. Hence, you have to evaluate carefully what is reasonable for your application needs and implement the solution accordingly.
- Optimal Cost: As you progress through your application and deployment design, you would be able to come up with multiple approaches to deploy the same application. However, one key aspect to be successful in SaaS is to ensure that you choose the most cost-effective model that not only meets your immediate needs but can cater to at least the near future needs, such as when the demand rises or slows down. You do not want to be spending overtly, but not so less that the application starts choking with very few users. Hence, it is important to strike the right balance. A rule of thumb that I like to follow is when choosing resource sizing always go on the conservative side. And, if the testing reveals higher configuration is needed, then only increase.
DevOps Considerations For SaaS
DevOps is so critical for SaaS that it is worth discussing it separately. The following are some key considerations.
- Continuous Delivery: The DevOps pipelines should be able to take the checked-in code, produce a build from it that then passes through various stages (QA, performance, final go/no go checks, production deploy) in an automated manner. This may involve having multiple pipelines (typically, per stage) and having an uber pipeline that pushes the build through each of these stages. Now, the pipelines may also take some time to develop, but it is a good idea to start defining the contracts for each pipeline so that the consumer pipelines do not need to worry about the details. Eventually, the goal should be to get completely hands-free or as close to it as possible.
- Use Version Control for everything including DevOps changes: For application code, it is generally well understood to use the master branch of the source control. However, it is equally important to do the same for any DevOps changes. For example, when you are rolling out infrastructure changes, these should also be checked into the source control, tested and then pushed to production.
- Agile Infrastructure: To be successful at SaaS, you want to make sure that your infrastructure is agile and can cope up with the changes in demand. As the demand goes up, it can scale appropriate tier and when the demand goes down release the non-required resources. This requires a certain level of experimentation and testing to get to the right balance. For example, you can use AWS auto-scaling capabilities to automatically scale up/down the infrastructure.
- Monitoring and Alerts: The stacks these days have multiple moving parts and troubleshooting could be a bit of a challenge. Hence, it is important to have the right monitoring and alerting mechanisms in place so that when things go wrong, you can troubleshoot the problem more quickly. It is a good idea to leverage from some of the core Cloud monitoring capabilities like centralized logging, alarms, and notifications on errors.
Other Considerations For SaaS
- Planning and Prioritization: Like any other successful project, SaaS projects also require planning and prioritization. While everyone wants to go for goals like “push every check in to production”, see what makes the most business sense and prioritize the important things first. Of course, having a stretch goal is not wrong. But, it is important to get the important things right first. For example, if you do not have a good unit testing and automation coverage and you are trying to push every code change to production, even if you accomplish it, the usefulness is questionable. It can backfire because things can start breaking too quickly in production and then the R&D team will be consumed in handling those.
- Monetization Model: SaaS also impacts the monetization model. While in on-premise you may be fine selling license for a certain amount, in SaaS you may have to rethink what is the most suitable model for your business. Do you want to use a subscription-based model, utilization-based model, a hybrid model, or something else altogether?
Hopefully, you got a better insight into what it takes to design a Cloud-based or SaaS application. It is certainly an enriching experience to see your application that involves so many different aspects, go live in production. As I always say, “Cloud is a journey and not a destination”. So, keep learning and evolving.
If you liked this post, you will find my AWS Advanced For Developers course helpful that focuses on many such best practices and techniques to design and deploy real-world applications in AWS.
Also published on Medium.