Monoliths, containers or serverless: what is the way to go?

Written by Journerist | Published 2017/12/27
Tech Story Tags: serverless

TLDRvia the TL;DR App

If I ask tech people about the cloud then I realize that there is no hype anymore. Since 2006 Amazon’s cloud called AWS allows people to manage their virtual infrastructure by using a simple UI or by infrastructure as code [1].

11 years later AWS extended its offering to more than 100 services. There are services for dynamic storages, managed databases, image and video recognition, machine learning, container provision and much more. It’s the most exciting and frightening drive that competes with open source.

In 90s open source software was an unusual appearing. Since 2000 more and more mature open source projects were created that are widely used in 2017.

Nowadays it seems like serverless is the new shiny way to create a modern application. They scale from zero to thousands of requests per second in a short amount of time. Additionally, I do not mess around with operations like updating servers, set up clusters and so on.

The pace of innovation in serverless seems to get faster and faster. ReInvent 2017 was amazing.

They added a lot more to the serverless chain [4] like:

  • Fargate a container based serverless offering,
  • Cloud9 an online IDE that was made to create and test serverless applications and
  • Traffic shifting for Lambda allows rollout updates gradually.

In 2014 AWS invented Lambda. For me, it was a questionable concept. Most of the tools that exist for classic development did not fit for lambda. Additionally, there are microservice based applications that use docker and Kubernetes to simplify operations.

It is hard to define when to use a monolith first [3], a service-oriented or a serverless approach. Since AWS added so many services around lambda, I can have similar automation and tooling chains that increase software development speed and quality.

Let’s see what scenarios out there exist and compare basic solutions against each other.

Comparisons

In the following chapters, I will talk about viable solutions for different types of applications. But I will talk about some basic concepts first:

Monolithic applications

The most used approach is to put everything in a single application. Maybe their frontend and backend are separated. Monoliths are big applications that grow more and more. Usually they are hard to maintain and to extend [6].

In the following scenarios, I will rarely reference to monolithic applications. More often I will talk about Webspace, static sites and self-managed server setups that most of the times are hosts monoliths.

Containers

The most popular container engine is docker. These handy isolated packages can be scaled, rolled back and distributed by container orchestration software like Kubernetes (k8s). The abstraction allows generalizing operational requirements that simplify operations a lot. I only need to pack my software in a container. This allows me, for example, to add more instances due to heavy load and distribute containers between multiple machines.

Setting up a Kubernetes cluster is complicated. But there are managed solutions like Googles Container Engine (GCE)or AWS’s Elastic Container Service for Kubernetes (EKS).

I will mainly talk about Kubernetes but most of the things mentioned are valid for other orchestration solutions as well.

Serverless

A fully managed system is serverless. It actually means that business logic runs in little functions. By uploading the code to the provider developers don’t need to worry about updating, uptime, scaling and so on.

In my examples, I will talk most of the times about AWS’s Lambda. There are other solutions that behave very similar and I don’t want to favor any solution. Alternatives are Google, Azure and IBM functions.

Host static sites

JavaScript enables developers to host dynamic websites that are static actually. I only need to use frameworks like React or Angular and leverage their tooling. By executing a single command all required files are generated that can be uploaded and opened in the browser.

A simple solution would be to buy Webspace for static html sites. But the downsides are scalability and flexibility. If I have a high load due to for example a social media post or I want to add a simple server-side script I am kind of stuck.

In this case, AWS is a good fit. By uploading my static files to an S3 bucket I have what I need. The costs are about a few cents because I pay per bandwidth. Even though, the application is cached and fast. On top of that, I can easily get free SSL certificates to use a secure and fast connection. Additionally, certificates are renewed automatically. Everything is scalable and if I need some dynamic execution I can leverage other AWS services.

I think I don’t need to explain why a container based or bare metal based solution is definitely an overkill.

Winner: AWS with S3 and CloudFront.

Host sites with simple server-side interactions

Many sites have dynamic parts like:

  • Contact forms,
  • Google captchas or
  • elements that can be changed like notes, todos or similar applications.

Webspace and self-managed servers

Similar to a simple HTML Webspace provider I can also buy Webspace for PHP or other languages. I will end up requiring special version updates of my runtime or not installed extensions. Over the time a virtual server can be the best fit. Anyways, this solution is cheap but starts getting more expensive related to the load I have. There is nothing comparable to auto-scaling available. Also, I need to manage my virtual server. Installing new updates, adding security and monitoring are challenging.

Kubernetes

This is the first time that I can think of a Kubernetes based solution. We would create 2 small services:

  • One for the static part and
  • one for the dynamic part.

As soon as more requirements appear we can either extend an existing service or add another service.

Auto-scaling and no downtime deployments come for free. I need to set up automated builds for each service. This is a challenging task. I need to

  • build applications,
  • package docker container and
  • deploying them into production.

This is the heaviest downside. Compared to what I actually need for my local development system it feels heavy to prepare things for Kubernetes. But if I have a good foundation for one service, adding another won’t be so hard anymore.

Serverless

In AWS I would use a similar approach to the static case. I would still host the static site in a public S3 bucket. As soon as dynamic content raises we can add a Lambda function. Especially simple scenarios like straight-forward CRUD use-cases or a verification of a google captcha is easy. By adding API Gateway, Lambda and DynamoDB we have a scalable system. Costs are still cheap and if I keep my logic small there is nothing to maintain.

Conclusion

K8s and serverless seems similar in comparison. But there is a big difference in pricing and configuration. Given that I don’t know any tooling it is still easier to set up AWS managed services from scratch because everything is integrated in a nice way. In contrast, if I try to build custom containers and set up my own git repository, GitLab, GitLab-CI within Kubernetes I need to tweak a few things.

Additionally, I need a decent amount of resources for k8s. Therefore the costs are higher compared to the serverless solution. For example, I require some resources for k8s itself, I will run something like Jenkins / GitLab-CI and my services. This will cost already about $40 per month. The biggest part comes from my CI infrastructure. Additionally, I need to update my images manually. Otherwise, they will degenerate and break in a bad moment. The costs of AWS depends on how often I use things because executions of my build pipeline cost a few cents.

Anyways, serverless is still easier to set up, maintain with lower costs.

Winner: AWS with S3, Cloudfront, lambda, DynamoDB

Run complex business applications

Many applications are either already complex from the beginning or will start to get complex over time. I define an e-commerce shop as a complex example. There are different domains. Areas like payment, product listing or shipment are domains that interact in some way with each other.

Handling complex applications well with multiple developers is what makes a business successful in long-term. Otherwise, the application will rot and turn into a big ball of mud [5]. If this is the case, sooner or later, I will start to refactor or to rewrite my application. Usually, this happens over time. The question is how fast it degenerates and how much well-developed parts are reusable.

I think we can skip the simple Webspace solution strategy. I will need a well-formed continuous integration platform with a comprehensive suite of tests. They will get slow and I need to optimize them / bump resources frequently.

Self-managed servers

If I have simple servers I need to maintain everything for myself. I am in full control of my test-, integration-, and production systems. Multiple machines need to have similar setups. I will use tools to administrate and configure machines automatically. Furthermore, developers are proud of their self-crafted working infrastructure and I can handle heavy peaks what also means servers idle most of the time.

Anyways, development teams need a lot of time to keep things running and to fix existing issues. Operations is always a bottleneck in this case because the most important thing is to create business value. About 15% of the work needs to be done related to monitor and tweak production systems. Advanced techniques like canary releases are very hard to implement because there is not enough time.

Another downside is that running another application on test- and production-systems seems to be challenging. It’s very hard to add new services because operation effort is high.

Kubernetes

Also, I can use a container orchestration software like Kubernetes. This simplifies operation requirements a lot. I have many useful things working out of the box like rolling updates, rollbacks and auto-scaling. Developers can easily prototype applications and bring them into production.

If I follow certain rules logging and related metrics will work too. Different technologies of docker container require a strategy for integration. But in general Kafka or HTTP is a widely supported tool/protocol.

All the challenges that I had with self-managed solutions are now manageable. The heaviest downside of the Host s_ites with simple server-side interactions_ example were costs and maintenance of tooling for continuous integration and deployment. But in this scenario, it’s totally worth the effort and the ratio compared to the feature development effort is reasonable.

Serverless

For now serverless seem to be a good fit for simple static and dynamic applications. If I have complex business models I am forced to create hundreds of lambda functions. I need to put a lot more effort into the general solution strategy. It does not end well if I create function over function repeating things over and over again. Business logic has invariants, policies, general rules that need to be fulfilled. I need to handle that in a central way.

There are different approaches. But one way is to create a library for my business logic that is used in lambda functions that centralizes important definitions for my business.

AWS can still be overwhelming if I touch it the first time. As the project starts to grow I want to have:

  • Version control system (GIT) (AWS Code Commit) and
  • Automation for testing and deployment (AWS Code Pipeline, Cloud formation, Code build, Code Deploy).

This is also a big piece but similar to a k8s solution, once everything around is set, extending is usually quite simple.

It’s a best practice to keep lambda functions small and split up certain areas that have no or only a few dependencies to other areas. This allows independent development of these areas without affecting other team’s domain so much. For example, in an e-commerce shop I should separate the item stock calculation from my payment logic. Both make use of a customer. But there is not much interference.

Conclusion

Kubernetes seems to be a good fit here. Having all the logic in a serverless environment is a challenging task. If my cloud provider changes something I need to adapt my things as well. Also, running the whole stack locally is not possible. It’s anyways hard to simulate production behaving but still… it’s very frightening to be so heavily depended on some one else’s system.

Winner: Kubernetes

Closing words

Virtual/bare-metal servers will decrease over time because they can not compete with fully managed cloud offerings anymore. Only in rare cases, I would go for a self-managed server environment. Don’t get me wrong, I love managing my own servers and it’s still important to understand what happens behind the scenes.

But if I lean back and think what are the bottlenecks in my development it’s usual operations. Additionally, costs are important and cloud offerings like Kubernetes and serverless allow us to scale on demand. This is not only important for our production system. Having fast test systems is also important and can be a bottleneck for feature development.

What I usually want is to develop business logic and run it with mature technologies. We don’t want to think about scalability, it should just work.

If you are interested in a serverless example check out my git repository. It contains a simple todo list example. Lambda functions were created with Cloud9. It also contains a basic AWS CodeBuild file that is used to create lambda function changesets. These can be used to update a running application in a controlled way.

I appreciate any comments and feedback. Also, clap for it (multiple times) if you enjoyed the reading.

References

[1] https://aws.amazon.com/de/blogs/aws/eight-years-and-counting-of-cloud-computing/

[2] https://sdtimes.com/amazon/amazon-introduces-lambda-containers/

[3] https://martinfowler.com/bliki/MonolithFirst.html

[4] https://aws.amazon.com/de/blogs/compute/serverless-reinvent-2017/

[5] https://en.wikipedia.org/wiki/Big_ball_of_mud

[6] https://www.thoughtworks.com/de/insights/blog/monoliths-are-bad-design-and-you-know-it


Published by HackerNoon on 2017/12/27