I’ve been thinking long and hard about the best approaches to designing serverless systems, and why it is so different.
(I am completely aware that the canonical implementation of serverless at present is on AWS with Lambda + API Gateway and that has a big impact on my thinking, but I am trying to abstract the specifics out to generalisations where I can.)
How Architectures come about
I’ve been around long enough in the tech world to have seen many different architectures around many different types of problem. What usually happens is that we have a few ideas, we talk about them, a conference or two happens, then some clever person writes The Blog Post to Rule All Blog Posts (or book/TED talk) on the subject, and voila. We have an “Architecture”.
The thing is, a large proportion of architectures have sprung out of enterprise. There’s a good reason for this. The money put into IT means that having a structure prior to starting is a good thing and apparently saves money. But often the architecture is over complicated and needs adaptation for a smaller implementation, because most companies don’t have enterprise level resourcing and skillsets. We reach a “middle ground” somewhere after a year or two that allows both enterprise and startups to use it, and then the architecture solidifies.
So… what about Serverless?
Serverless is about Events
This may seem obvious, but it’s not always understood. Events are simple things to understand:
“Geoff bought a car”
“Sally opened an account”
And most of the time, the systems that we’ve built have been relatively simple. We take that information and file it somewhere in a database and then pat ourselves on the back for ensuring that the server still works and no data was lost.
That’s never it.
The normal pattern is to worry about the extra stuff immediately in the programming. When we receive the event, we store the data, then we do something (or many things) with it. So we might end up with pseudo code like this:
This is not really how event programming is supposed to work. You end up with multiple failure points in the code, and a mess when something goes wrong that wasn’t tested for e.g. a user enters an email with a recent tld and the validation hasn’t been updated.
The problem with most current technical architectures and frameworks like this is the implication that they have complete access to the rest of the code base and data sources. There is an expected code coherence in the system between where the work of coding is done and any actions that you do based on interactions in the system.
Simply put, all the code is in one big block of bytes. It’s not in multiple systems. So if the code is erroring then it’s likely to error over and over again because it’s probably the same code that’s doing it.
Event architectures are often more distributed and loosely coupled as a general rule, and that is definitely more akin to the serverless approach.
But the loosely coupled and stateless nature of each function’s code is actually an iteration beyond most event architectures.
Serverless Event Management
In my view, Serverless architecture should be more about receiving an event, storing the event data, and then saying “Thanks. I’ve received it.” to whichever event producer sent it.
Once you have received an event into your loosely coupled event system, you can then do whatever you like with it.
When you have finished, you can then provide a message of some description back to the event producer, or not as required.
This relies on a very different approach to coding than is encountered with most web based frameworks. This kind of event/messaging system is closer to mobile API programming, which has often utilised the push notifications inherent in the platform, but still (in my experience) has an expectation of coherence of code base.
So maybe what should happen in the above scenario is this:
This approach allows for more fault tolerance. It moves the workflow from the codebase into the infrastructure and relies on the infrastructure more (cloud providers should love this — choose wisely!) to deliver the solution.
It also allows the API to respond rapidly with a useful message which (paraphrased) is “Thank you! Got the event. We’ll let you know when you something changes”.
This should also make managing and testing each function call a significant amount easier in my view. You are testing simpler things. In fact, it may even remove a large proportion of the unnecessary testing that I often see.
Still working this one through
I’m just starting to think these ideas out and implement these ideas into our systems. I know that there are existing architectures out there (SOA, EDA, BBQ… no… not the last one… I must be hungry) that deal with loosely coupled and distributed systems. IoT is also a space where this kind of an idea is a given too. However, I do think that Serverless is an iteration beyond the autoscaling PaaS and container based solutions and frameworks because none of those previous systems envisaged such a fragmented and loosely coupled codebase as well.
So maybe the core elements of Serverless are:
Loosely coupled managed services combined with stateless loosely coupled micro-functions
There will be issues
I’m sure there are problems with the implementation of this, but it’s definitely something I’m going to try to figure out as I go forwards.
AWS Lambda isn’t everything, but combining it with all the other AWS services such as Cognito, API Gateway, SNS, SQS, S3… it does seem to have a lot of these ideas already there to experiment and try out new solutions.
Maybe the other providers need to focus less on the micro-compute side and more on the loosely coupled services. It’s not all about VMs and autoscaling any more.
Serverless is about flows and streams of data and events and messages.
This is the future (imho)