Content outline

Jun 23, 2024
6 Min read

3 cloud-native deployment models for monolithic web applications

Thinking of rewriting your monolith in microservices?

Creating a brand new web app and opting for microservices just becasue you want to be cloud-native?

Secretly worrying that you are not cloud-native while others are because you are stuck with a monolith?

Read this now.

You can make your monolith cloud-native by deploying it cloud-natively.

Outline

What is a monolith

A monolithic software application (AKA a monolith) is a server-side software application developed and deployed as a single unit.

In contrast, a microservices application is composed of multiple units (called microservices) that are developed and deployed independently from each other.

Before the era of the microservices, the monoliths dominated the web. The popular web development frameworks like Django, Ruby on Rails, and Symfony that came to light before the microservices, adopted a monolithic architecture.

Microservices started making waves in the software industry in 2011. Many developers considered microservices as the modern standard for web applications and took it up in favor of the monolithic architecture. Hot debates went on in forums and social media about whether monoliths are dying.

After more than a decade from the advent of microservices, we can confidently say that monoliths are not dead. Same as microservices, monolithic is an architectural pattern that has its merits. And monoliths will live as long as the Internet.

But the DevOps movement has left the monoliths behind. All tools in the cloud-native ecosystem are geared to serve microservices applications running on Kubernetes. And, many rewrote their monoliths in microservices just to get the advantage of this cloud-native ecosystem.

But the monolithic pattern is well-loved by some developers due to its simplicity. So, how can we get cloud-native benefits without rewriting our monoliths in microservices?

By deploying our monolith cloud-natively.

How we traditionally deployed monoliths

We used to deploy our monoliths by directly installing the application with the runtime and the dependencies on the OS of a virtual or physical server.

This method is easy and straightforward. But not very cloud-native.

To update our monolith, we must either install the new version on the production server itself risking the live traffic or start everything from scratch on a new server. But that’s a lot of work.

Sure we can automate this type of work with tools like Ansible. But it takes a considerable time to set up a new virtual server and push a new version to production. What if we want to roll back? Again we must install the old version from scratch.

Things get further complicated if our old and new versions have different OS-level dependencies.

Scaling out our monolithic application also requires provisioning new servers and installing from scratch. If we want to do this type of scaling operations several times a day, we would be spending most of our time troubleshooting application startup failures.

Clearly, the traditional deployment method for monoliths is not cloud-native. It does not allow us to exploit the agility of the cloud.

How to deploy a monolith cloud-natively

We can counter this non-cloud-native nature of monoliths with alternative deployment models:

  1. Monolith on Docker Engine
  2. Monolith on Kubernetes
  3. Monolith on PAAS

Cloud-native deployment strategies.

Deployment model #1: Monolith on Docker Engine

Docker Engine is the platform from Docker for running containerized applications. While containers were originally intended for microservices, there’s nothing wrong with containerizing a monolithic application.

In fact, newer versions of Ruby on Rails create a Dockerfile when initializing a new application. This Dockerfile can create a production-ready container image of our Rails app.

All monolithic application development frameworks may not ship with a Dockerfile like Rails does. But we can write a Dockerfile and create a container image for any monolithic application.

Instead of deploying our monolith directly on the OS of a virtual server, now we can install Docker Engine and deploy our containerized monolith on Docker.

This model overcomes most of the limitations in the traditional monolithic deployment model.

Now it’s easy and straightforward to push a new version of our monolith to production. Instead of setting up everything from scratch we can build and deploy a Docker image of the new version. If something goes wrong we can instantly switch back by starting up the old Docker image.

Scaling our monolith on the Docker engine is also relatively easier because we don’t have to set up everything from scratch. We can scale out by running the Docker image on a new server.

If you are working on a monolith, try deploying it on Docker instead of installing it directly on the virtual server OS. You’ll be taking a big stride in making your application cloud-native.

Deployment model #2: Monolith on Kubernetes

Kubernetes is the primary platform for microservices applications. But, as long as we can create a container image of our monolith, we can deploy it on Kubernetes.

Once our monolith is running on Kubernetes we are entitled to all built-in Kubernetes features like scaling and healing. Also, we can use most of the open-source tools in the cloud-native ecosystem to implement continuous deployment, logging, monitoring, etc.

It may be enticing to opt-in for Kubernetes as the platform of choice for deploying any monolith just because Kubernetes is packed with more features and is more scalable than Docker.

But running a Kubernetes cluster in production is no easy feat. The operational cost and the effort of Kubernetes is not always justifiable. But there are certain cases where Kubernetes is the sensible choice for a monolith.

If you are already running Kubernetes in production and you want to launch a new monolithic application, there’s no reason not to use that existing Kubernetes cluster to run the monolith too.

Also if you are following the majestic monolith architecture and want to transform your monolith into a citadel, your software application will be a large monolith supported by a number of smaller microservices.

Running this entire setup on Kubernetes will help you unify your deployment procedure for the monolith as well as the microservices.

Deployment model #3 Monolith on PAAS

PAAS concept came to life in 2006, way before Docker and Kubernetes. The Heroku platform launched in 2007, played a key role in popularizing PAAS. Today, many cloud service providers are offering PAAS solutions for a range of programming languages and application development frameworks.

PAAS offers a platform where we can deploy the code directly without worrying about the underlying computing infrastructure. The PAAS provider takes care of provisioning the computing resources to match the loading of our software application thus relieving us completely from the burden of operating cloud infra.

PAAS providers also offer toolchains to automate the application deployment right from the developer workstation. So PAAS is quick and easy to get started.

Solo developers and small teams love PAAS for its ability to go to market quickly without messing around with virtual machines or Kubernetes.

A downside of PAAS is that you don’t get access to the underlying cloud infra so you have limited room for customizing the application runtime. This may not be a problem in the early days of your application. But it can hamper your growth in the future.

Cost is the next problem with PAAS. PAAS platforms are priced in incremental steps of application metrics like the number of HTTP requests, database records, network bandwidth, etc. When you cross a certain threshold you enter the next pricing step.

At higher scales, PAAS could be a lot more expensive than the other two options. But, that’s a trade-off for being relieved from the workload of operating the cloud infrastructure .

Wrapping up

Cloud-native is associated with microservices in most discussions. But in reality, cloud-native is all about exploiting the agility and the dynamism of modern cloud infrastructure.

The traditional deployment model of monoliths - installing the application directly on the OS - allows very little room for us to exploit these qualities of the modern cloud.

But with the alternative models we discussed here we can exploit those qualities to a certain extent.

So, how would you deploy your next monolith? Share your thoughts in the comments below.

You can also reach us via email or Twitter.