When the first tutorials started to come out using AWS Lambda and API Gateway, back in 2015, it was unsurprising to find that they focussed largely on replicating the microservice. However, it became increasingly clear to those that used AWS Lambda at scale and over time that there were significant limits to the microservices approach with AWS Lambda… at least there were limits as to how most people thought that microservices should be built.
Let’s talk about the “why” of microservices
Microservices exist primarily because of frustration with monolithic applications. A monolith is simply an application where all the logic is put into the same logical codebase.
Back when we were building for the single server environment, when it was expensive to have multiple servers or provision more, this was the default way that applications were built. And deploying a monolith meant that you deployed a part or the whole of the entire application to a server.
Deploying monoliths also meant that you had to be sure you weren’t breaking anything. Very often a small change would bring the entire server down, and the entire application.
So when cloud came along, with the ability to provision instances at a click in minutes, not days or weeks, the ability to then separate concerns was obvious.
So breaking up the monolith became an obvious thing to do, and the idea of microservices was born.
Instead of building a monolith with every piece of logic on a single server/instance you could have a part of an application on different instances and connect them via some lightweight communication protocol — usually an HTTP API interface.
So application architecture moved from monoliths to microservices.
The “why” is interesting though. The value in doing this is that if a change is made, you aren’t changing the entire codebase, you are only changing a microservice — only a constituent part of the application. That means, very simply that you don’t take an entire application down.
That’s the theory anyway, and it’s a better theory than the monolith, but it’s not perfect.
The key for each service is…
The service interface
This is normally some form of HTTP interface (or at least this is the most common way of doing it). This is normally no problem, except that when you end up with large numbers of services, it can become a big problem coordinating all of that.
Moving to serverless
So when the first serverless applications started to get built on AWS, the initial approach was “let’s build microservices”…
Which meant: build an API Gateway interface, with a Lambda function behind it and a switch statement to act as a router.
Each API Gateway becomes a service interface, and that seems logical.
And you can build a series of services that then scale separately from each other, which makes a lot of sense in some ways.
Except it doesn’t quite make sense when you understand that AWS Lambda functions and FaaS in general shouldn’t be treated the same as an instance/server.
Because while there are servers underneath the hood (hey there are servers underneath most of the stuff that runs on the internet but nobody points that out like “S3 still has servers” or “BigTable still has servers” or “Azure Active Directory still has servers”… sigh) there is an assumption that you should simply treat a FaaS function the same as a service… a “minilith” as some have called it.
The problem is that this misses what I think is the key to serverless:
Serverless is all about events
Serverless, events and triggers
Serverless systems are inherently event driven systems and therefore are event driven architectures. This changes how you approach their development, their management and their architecture.
Within a microservices solution, the intent is to be responsive to the interface and that is the primary mechanism for interaction with the logic.
Within a serverless solution, the intent is to be response to events that occur, and an API is actually only a mechanism for generating events.
Within the AWS ecosystem, which is the most mature of the serverless ecosystems, the API is not seen as the primary interface. Events are much more important.
And that is why there are nearly 50 events that can trigger a Lambda function to run from other AWS services.
And the advice is always that if you can trigger a Lambda function without going through an API Gateway, then that is a significantly faster and more efficient operation than using an API Gateway, especially if you are triggering from within another AWS interface.
And taking a look at the Serverless Best Practices you will see some other elements that diverge from the way that many people architect microservices
Serverless Best Practices
Within the community we’ve been debating the best practices for many years, but there are a few that have been…
Primarily the key is the unidirectionality of functions. Most microservices tend to use a request-response type of architecture, because that is how most web applications tend to run. Functions within a serverless application tend to prefer being unidirectional and using queues as circuit breakers, so request-response becomes a lot less common.
The data layer is also managed and understood differently as well. The best practice is to have multiple functions rather than a single proxy function with a switch statement.
And the idea of multiple functions also gives you an additional benefit over microservices. If a function errors, then because it is stateless (or at least, it should be!), then it only affects that function rather than the rest of the application. Really useful part of not building a minilith right there!
So simply transferring knowledge directly from microservices to serverless gives you a few of the benefits, but really misses a large part of what makes serverless applications so valuable.
Microservices tend to diverge in multiple ways from a well architected serverless application, which means that while it is possible to build microservices with a serverless backend, there actually isn’t a straight forward direct path between microservices and serverless.
The path from microservices to serverless
So what is the path from microservices to serverless? Is there a straight forward way to learn the basics to make it easier to transition from one to the other, since microservices are so pervasive?
This is something I think the serverless world is wrestling with. There was a massive thread recently on twitter where we talked around this kind of subject. It’s worth referencing it here, if only to see what kind of thing the community talks about (go up and down the various replies and you’ll see numerous conversations around this topic, although none directly mention microservices).
Some of the tools that are out there tell you that they make it easy to build serverless applications, but then end up being that platform that you have to build on. I don’t think this adds value or makes anybody understand the architectural style any better.
We are acutely aware as a community that we’re talking up serverless as the future, but not necessarily making it easy to transition from older architectural styles or making it clear when serverless is the right (and occasionally not the right) choice.
There’s a reason for that.
It’s not that easy to transition a person’s thinking yet.
It’s easy to build a Lambda function.
But it’s not easy to build a well architected serverless application.
Because it does require a change in mindset, and that’s relatively hard.
And as I’ve said a number of times in various ways, we need to stop getting people to “hello world” and leaving them there because that’s what a lot of tech people think is all that’s needed.
The reason I wrote a Serverless Best Practices was to try to help people to consider that they shouldn’t be making assumptions as to how serverless applications are built based on their existing knowledge.
The tools that we’re using to build serverless solutions are currently the tools we use for building cloud 1.0 applications, and they are not completely fit for purpose.
Those tools are imperfect, and we’re all trying to work to explain and improve them as best we can.
What we need from you
I think the community is actually very open to helping people learn and grow in building serverless solutions.
So what we need as a community is your questions:
- What are you struggling with?
- Where are the holes?
- What tutorials are missing?
And anything like that.
And I am available to help companies to make this transition.
I’ve worked with senior leaders and CTOs and CEOs to help identify what value is created in using a serverless approach in a company, and I’m happy to do that for other companies.
I’m very happy to help. Get in touch on LinkedIn here: