TLDR; If you really boil it down, Serverless (FaaS) setups are Microservices. What most blog posts refer to as Serverless vs. Microservices isn’t a “vs” at all; they are typically just describing trade-offs between always-on or on-demand provisioning of compute resources and the specific provider ecosystems you could use. An important decision for sure, but not the radical sea-change proponents claim it to be.
People often ask whether to use Serverless or Microservices for their core architecture. Much has been written on the subject online, making it seem like a crucial decision between two incompatible setups that must be fundamentally at odds with each other. On the contrary, they’re as similar as two flavors of ice cream – you might favor chocolate chip but usually strawberry can do the job fine too.
Serverless architectures are composed of small, autonomous services (or functions) that run in response to events. Those events can be internal or external API calls, scheduled events, or ones originating from user/3rd party services. If this sounds familiar, it’s because we could change the word ‘Serverless’ with ‘Microservices’ and the definition would still hold true.
For a while, saying Serverless meant bundling code as a zip file and having it run as an AWS Lambda, Google Cloud Function or Azure Functions, whereas saying Microservices conjures the words containers, kubernetes or running your own platform. Then in December 2020, AWS introduced container-image support for AWS Lambda, making that distinction obsolete; Google and Azure followed suit. One more characteristic that suggests they’re the same.
There are 2 ways to execute code in a cloud setting: always-on servers, and on-demand execution.
Always-on simply means that the compute engine running your application will stay on regardless of whether a user is using your application or if it’s completely idle. Let’s take Spotify as an example: the majority of US Spotify users will start listening to music around the same time as they commute to work through car traffic, and Spotify would need to put enough always-on compute in place to meet it.
The appealing thing about Always-On resources is that they’re always ready to go. If Spotify was running exclusively on Always-On cloud resources, the hundreds of thousands of early coffee drinking music listeners would be funneled into the ready-to-go servers with no delays, music starts flowing instantaneously. However, after everyone gets to work and turns their music off, the cloud resources powering them remain on, burning through cash and power.
On-demand computing on the other hand, and as the name suggests, asks you to pay only for the time you use the resources for, and can be as granular as the number of activations your function had and the time they spent in milliseconds,. The tradeoff however is whenever more servers are needed to run your application, the cloud providers need to spin them up and add them to the pool, and that takes time.
In the same Spotify example from before, if Spotify was running exclusively on On-Demand resources, when everyone got to their workplace and stopped listening to music, Spotify would stop paying the cloud providers because they’re no longer using the app. However, as people start commuting home, more cloud servers are needed to handle more users, so the cloud providers start spinning them up – which is great because Spotify would be only paying for real user usage. However, spinning those resources up takes a bit of time, which means users will experience a level of delay until music starts playing, degrading the user experience.
There are many ways to tweak and optimize so those tradeoffs are more manageable, but in the end of the day they are tradeoffs – and that’s the important thing to remember.
Different services, different tradeoffs
Other characteristics like deployment speed, operational complexity, scalability, service coupling levels and most other characteristics attributed to Serverless vs. Microservices are in reality product decisions. Each cloud provider and service is designed to solve for a class of workloads.
For example, both AWS Lambda and AWS Fargate can run containers, and both can run the majority of workloads. Lambda is more managed, but with Fargate you get better controls on the types of hardware configurations you want your containers to run on when compared to Lambdas which are more restrictive / pre-defined.
Some services have lower latency at the expense of reliability, others have higher reliability at the expense of throughput, and some are great for both but cost significantly more. In most mature solutions, the question isn’t which one is better, but which one satisfies the requirements of the system you’re trying to build.
Which service should I use?
Many factors go into choosing the appropriate set of technologies and the goal should always be to satisfy the product requirements the organization sets for itself. The biggest challenge most of us experience however are shifting requirements over time – which leads to an endless loop of platform re-architecting.
That’s why we introduced Adaptive Architectures, the next Cloud Architecture to supersede Microservices and Monoliths. It allows for change in the underlying cloud architecture while preserving the behavior of applications.
Klotho is our implementation of Adaptive Architectures. Simply start with your own application and write nothing but code. In it, you provide us with your intent through high-level annotations. You run Klotho, and that’s it, your application is now cloud native.
We built Klotho using compiler theory, applied distributed systems, and constraint-based planning, three groups of people and technologies that have not traditionally worked together. Combining those 3 disciplines allowed us to create something fundamentally new and transformative that enables the cloud architecture of the next 10 years.