Software-as-a-Service (SaaS) offers a compelling opportunity for developers who create software originally intended to run at web scale. Having a single code base that runs a variety of enterprise-level business applications reduces the labor that goes into creating and maintaining the software that supports it all. The promise of "one code base to rule them all" makes developing SaaS platforms a value proposition that's hard to ignore—as long as the development team has the expertise to make their ideas real. You need to know a thing or two about creating SaaS platforms. They are a bit of a different beast than single-purpose web applications.
There are two ways to create a SaaS platform. One is the "greenfield" approach: Build a SaaS platform from scratch. The other way is to transform an existing web application into a SaaS platform.
This article takes a look at the second way. I describe how to transform an existing web application into a SaaS platform with the help of a concrete, yet fictitious, business named Clyde's Clarinets. The goal of the article is to describe how to transform Clyde's Clarinets into a SaaS platform named Instrument Resellers.
Understanding the example business scenario
Clyde's Clarinets is a successful business revolving around an application that Clyde developed to streamline his business's operation. The business uses the software to support the workflow of buying used clarinets online, refurbishing them, and finally reselling them at a profit.
The application has accelerated business growth significantly. As a result, Clyde thinks the software can benefit others too. His plan is to refactor the application into a full-blown SaaS platform.
Clyde's Clarinets stands in here for many real-world examples where a company builds some software for its own use, realizes the application will be valuable to others, and then transforms the custom application into a SaaS platform they can sell on a subscription basis to other businesses.
Clyde's Clarinets works as follows:
-
The application scours the internet looking for used clarinets for sale. The application keeps a list of clarinets identified as candidates for purchase.
-
The list is presented to an expert human being, who selects clarinets to buy from the list. The application makes the actual purchase and keeps track of purchasing activity. The application also keeps track of refurbishing and resale activities.
-
When a purchased clarinet is received from the seller, a human declares the instrument as received. After a clarinet is refurbished, a human also marks that task as complete.
-
After refurbishing is completed, a human makes a photo and a video of the clarinet being played and uploads the media to the application.
-
The application then posts the clarinet information, sale price, photo, and video on a variety of resale websites. The application interacts with the resale sites to discover a buyer and verify payment.
-
Once a clarinet is sold, the Clyde's Clarinets application notifies the company's shipping department to package and send the sold item to the buyer. The shipping department enters the shipping information into the Clyde's Clarinets application.
Figure 1 illustrates the process just described.
Clyde's Clarinets is an attractive business model. There are a lot of clarinet players in the world, and Clyde's Clarinets has made a good business by providing these musicians with high-quality refurbished instruments. In fact, the business model is so good that the developers of Clyde's Clarinets want to expand their enterprise to other instruments and make their system available to other musical instrument resellers as a brand-specific application.
But presently, the software supports only clarinets under the name Clyde's Clarinets. The question is how to transform the domain-specific clarinet business into one that will support a variety of instruments and a variety of resellers.
The key is to discover the abstract patterns that are the foundation of the application. If the abstract patterns are generic enough, the application can be expanded to SaaS. If the patterns are too specific, the application will be hard to transform. A SaaS platform can't be everything to everyone, but it also can't be so narrow in scope that it can't scale up to support a lot of customers. Again, the key is understanding the abstract patterns in play to determine whether a generic model exists.
Looking for the generic patterns
Clyde's Clarinets is a good candidate for transformation into a SaaS platform because its underlying behavior is generic. Figure 2 reproduces Clyde's Clarinets business model with more generic text.
Figure 2 is identical to Figure 1 except for one key difference. The subject of the workflow in Figure 1 is a clarinet, while in Figure 2 it can be any instrument. Because substituting the term "instrument" for "clarinet" doesn't clash with the overall intention of the workflow supported by the application, we can deduce that there is indeed a generic pattern in play.
The existence of the generic pattern means that Clyde's Clarinets is a good candidate for conversion to SaaS. However, two more conditions must be satisfied to enable the conversion. First, Clyde's Clarinets's software needs to separate logic from configuration. Second, the application needs to be hosted in an infrastructure that can support a large number of SaaS customers and their users.
In the next sections, we'll take a look at the details.
Separate logic from configuration
As explained in the previous section, to convert Clyde's Clarinets to a SaaS platform, the application's logic must be generic. Nothing specifically about a clarinet can be hard coded into the software or into the application's underlying data model. Specifics should be controlled by the configuration.
Moving specificity into the configuration might seem like a straightforward undertaking, but sometimes specificity can be baked into software in the most insidious of ways. Two of the usual culprits are non-generic data models and hard-coded strings that are specific to the business domain. Let's examine each condition.
Beware of non-generic data models
Take a look at the following Java entity bean. The bean represents the data model that describes a musical instrument:
public enum InstrumentType {A, B_FLAT, BASS}
public class Instrument {
public String name;
public String description;
public InstrumentType instrumentType;
public String manufacturer;
public double price;
}
At first glance, the data model might seem like a generic description of a musical instrument, but it's not. Note that the instrumentType
property is an enum of type InstrumentType
that lists only three possible values: A, B-flat, and bass. Limiting the InstrumentType
values violates the generic intention. Why? Only a few instruments have those particular types. There is no such thing as a B-flat flute or a B-flat oboe. Thus, the data model could never be used to sell flutes or oboes.
Granted, this constraint is not knowledge a lay programmer might have. But the first time a user tries to define a flute on the Clyde's Clarinets SaaS platform (now renamed Instrument Resellers) the shortcoming will become glaringly apparent. It's a significant issue and one that needs to be addressed before the SaaS can be exposed to the public.
Non-generic data models can be a real showstopper when converting a web application to a SaaS platform. Many times they're not obvious. Thus, when considering a conversion, make sure to set aside enough time to conduct a detailed analysis of the web application's data structures and refactor non-generic ones into generic versions.
Beware of strings hard coded to the business domain
Inappropriate specificity goes beyond data models. It can also appear within the intent of the application itself. Keep in mind that presently the web application is specifically about Clyde's Clarinets. There might be any number of references to the name Clyde's Clarinets in the application's web pages. Transforming the web app into a suitable SaaS platform usable by a number of resellers probably requires some changes to the code.
There are two approaches that a developer can take to make the change. One is to dedicate a unique copy of the source code to each reseller. Before that code is released, a developer executes a search and replace on the instance of the code base dedicated to the reseller to substitute the reseller's name throughout the application—for example replacing each occurrence of "Clyde's Clarinets" with "Gloria's Guitars."
This is by no means an optimal approach. Duplicating instances and then making changes in those instances is risky. The copy and paste approach violates the Don't Repeat Yourself (DRY) rule, an essential principle of good software design. Eventually, so many special copies of the application will be released into production that maintenance will become an ongoing nightmare.
The better alternative is to maintain a generic code base for application logic and declare application specifics in configuration files or a database. Separating specifics from generic behavior helps support a variety of business domains, but is also useful for larger concerns such as serving an international user base. For example, hard coding an application to display text only in English excludes it from general-purpose use in regions such as Asia and South America. It's more versatile to put such information in a database and bind the localized terms to the UI according to a locale defined in the software.
The takeaway is this: A well designed SaaS platform, whether built from scratch or refactored from an existing web application, separates logic from configuration to the finest grain of detail.
Identify a computing environment that can scale as the service grows
SaaS platforms require a higher degree of versatility and scalability than a single-purpose web application usually requires. To watch this evolution, suppose that Clyde's Clarinets starts out running on a single application server that uses a dedicated database server (Figure 3). This is quite conceivable for a small company serving a musical clientele.
As Clyde's Clarinets grows, the team needs to add a load balancer along with duplicate application servers and database instances, all of which run on either bare metal or virtual machines (VMs) to handle increased traffic (Figure 4).
The role of containers
Once the Clyde's Clarinets web application is converted to the Instrument Resellers SaaS, manually adding machines and servers pushes the limits of human capability. Many companies try to address the scaling problem by converting all machines to VMs and then automating the VM provisioning process.
But this approach has its limits too. VMs are slow to spin up. Slowly provisioning a VM can be tolerable when running a single web application, but when you have a SaaS platform that might support hundreds of companies and each company is supporting tens of thousands of users, scaling up using only VMs is unacceptable. The scaling is just too slow. Therefore, the modern solution uses containers (Figure 5) on an orchestration platform such as Kubernetes.
A container relies on the host operating system to implement isolation at the process, memory, and file system levels. The encapsulation provided by containers makes it possible to run dozens, maybe hundreds of containers on a single physical or virtual machine in a controlled manner, depending on how the host is configured.
A significant benefit of using containers is that they load very fast—an order of magnitude faster than VMs. Thus, container technology is well suited to applications that need to scale up and down according to current traffic demands.
The role of Kubernetes
For container technology to be useful in an automated manner at web scale, some sort of orchestration platform is needed. Just as with virtual machines, it doesn't make any sense to base container deployment on manual provisioning.
This is where the Kubernetes container orchestration technology comes into play. Kubernetes solves many of the problems that go with running applications and services on containers at web scale. The tradeoff is that Kubernetes is complex in terms of both environment configuration and physical hosting.
To refactor a web application such as Clyde's Clarinets into a set of Kubernetes containers and services could require some work. And then, once the work is done, the resulting application needs to be provisioned into a Kubernetes cluster. That Kubernetes cluster needs to be deployed to a set of virtual machines or, depending on the needs of the company running the SaaS application, a set of bare metal computers.
Scalable hosting
A single-instance application such as Clyde's Clarinets can be hosted on a Kubernetes cluster made up of a small number of virtual machines hosted in a private data center, or spun up and running on a cloud provider such as IBM Cloud.
However, spinning up a SaaS platform such as Instruments Reseller manually on a Kubernetes cluster, and hosting it on a few VMs, doesn't suffice. It's just too much work for a human to do. Something more is needed: A cloud-native Kubernetes hosting solution such as Red Hat OpenShift. Cloud-native platforms are intended to run at massive web scale in an automated manner.
The benefit of using a cloud-native provider to host SaaS is that you can focus on doing the work that goes into designing, maintaining, and improving the SaaS. Developers in this scenario don't need to do most of the work that goes with maintaining the SaaS at scale. They don't have to pay a lot of attention to the number of running VMs, scaling containers up or down to support the current load on the cluster, or addressing environmental issues. SaaS developers focus on the logic and configuration of the software, while the cloud native providers focus on the Kubernetes infrastructure (Figure 6).
Whether you decide to use OpenShift or another container platform, the important thing to understand about computing environments is that just converting code from a single instance web application to a SaaS platform is not the only work that goes into the SaaS transformation process. A computing environment that can support the SaaS at web scale matters a lot.
Putting SaaS on a cloud provider and container platform that can scale dynamically and seamlessly according to the service's needs provides significantly more value than just ensuring that the environment can meet expected nominal demand. Also, while scaling up to meet record high levels of demand is important, so is scaling down to minimize cost at times that customers are not using the application.
Remember, a SaaS product is intended to be used by a large number of companies and their users. Where it runs is just as important as how it runs. Determining the computing environment is an important decision.
Architecture, configurability, and hosting are all important
Software-as-a-Service continues to grow in popularity. Applications such as word processors and spreadsheets that used to be installed and run directly on the computer are now SaaS applications that run in a web browser. The same is true of more complex services such as video conferencing and even video editing.
SaaS platforms that are intended for tens of thousands or even millions of users are the future of software architecture. This model offers efficiency and opportunity. But along with such benefits comes complexity. Luckily, a good deal of the operational complexity created by SaaS can be delegated to a cloud native provider that specializes in hosting SaaS platforms.
Still, consideration needs to be given to the SaaS architecture. It's essential in SaaS design to separate logic from configuration down to the deepest levels, from data structures to localization terms.
The key to making SaaS platforms work is versatility. An application that separates logic and configuration in a fine-grained manner is more versatile than those in which hardcoding is inextricably embedded in the software.
Not every web application can be transformed into a SaaS platform. Some are just too specific to the business domain. But web applications whose underlying patterns are generic to a variety of businesses are good candidates for conversion.
Then it's a question of doing the refactoring work to make the generic patterns useful to a variety of customers. Once the code has been transformed, the last piece of work is to identify a reliable, resilient hosting infrastructure that can scale the SaaS platform up or down depending on the traffic demands.
Last updated: September 20, 2023