Thoughts on Serverless
The Rise of Serverless
It seems every year at least one new architectural buzzword is coined, and a new style of programming emerges that promises to be the one true way to build systems that will solve all your problems.
In recent years we've had CQRS, Microservices, Containers, Actor Model, and now "Serverless" is the next big thing, complete with its own books, conferences, and even a Martin Fowler bliki entry.
I've been following this with a lot of interest, particularly since I've been playing with Azure Functions, which is Microsoft's offering in the serverless space.
The concept of serverless architectures has attracted a lot of excited interest (and hype) as well as some ridicule (and cynicism), so here's my take on it.
Naming Things is Hard
Let's start with the name "serverless", which is patently ridiculous! Serverless would be more appropriate name for the first programs I ever wrote as a child on my dad's BBC micro which wasn't connected to a server or network of any kind.
The irony is that if you have a serverless architecture there are probably many more servers involved than if you had created a traditional monolithic backend!
What is Serverless?
But gripes about the name aside, what does "serverless" actually mean? The way I see it, serverless is a style of architecting applications where you avoid using traditional backend servers, such as virtual machines running web servers, databases or background tasks.
Relying on Third Party Services
Instead, you rely wherever possible on third party services who can offer core pieces of functionality and manage the servers for you. So for example, you might use Auth0 for your authentication, SendGrid for your email, Stripe for payment processing, SQL Azure or Firebase for your data, and so on.
Now so far, you're probably thinking, that's just Paas (or Baas - Backend as a service ) right? Many cloud deployed systems are already incorporating services like these anyway anyway. Well, third party services can only get you so far. At some point you need to write a bunch of your own code.
And this is where traditionally you might create some web APIs, maybe an ASP.NET MVC app hosted on IIS, or a Windows service listening on queues and running on a Virtual Machine.
Deploying Individual Functions
But serverless encourages us to deploy our code in the smallest units possible - at the function level. This is what Azure Functions (and rival offerings such as AWS Lambda)) offer. They allow you to deploy a single function that is listening on a web endpoint, or processing messages from a queue, or running on a schedule. Each function has an “event” that it is waiting for to trigger it.
With this style, all the boilerplate is abstracted away for you. You don't need to set up the OWIN pipeline and logging. You don't need to write the code that connects to the queue and polls for messages. You just write the bit of code that responds to the event you are interested in.
And you don't need to know or care about what server your function is hosted on, or even how many servers there are. That's all taken care of you by the platform. (Hence the name "serverless" which makes a bit more sense viewed in this light)
So in some ways, serverless could be called a "nanoservices" architecture - taking microservices to the extreme where each one is essentially a single function. It's taking the "Single Responsibility Principle" to the next level where your unit of deployment is just a single function.
The fact that the server is abstracted away means your functions need to be stateless, since you don't know which server will handle the next event.
Many serverless advocates also recommend reaching directly from the client into third party services rather than stepping through intermediate layers. This one is a bit more controversial, especially if you are letting the client connect to the database, and it requires a rich database security model where users can be granted permissions on a granular level. But done right, this idea has potential to greatly simplify the flow of data through your system with performance, cost and maintainability benefits.
The Benefits of Serverless
So, that's a bit about what serverless is (and I encourage you to watch this talk if you want a bit more depth). But what is this style of architecture good for? Why would we want to use it?
Well, first of all, it's great for speed of movement. Combining third party services with something like Azure Functions or AWS Lambda allows you to move rapidly and prototype quickly. Functions are trivially easy to create, and within minutes you can have a back end set up as a proof of concept.
The next benefit is not having to manage servers. You're not provisioning the hardware, installing and patching the OS. You're not even installing, configuring and patching application frameworks like .NET and IIS. Instead you just need to hand it your code and its up and running instantly. And deploying your code is trivially easy, often as simple as pushing to a Git remote.
Another big benefit is the cost model. Azure Functions and AWS Lambda both offer a pay only when you're running model. So if you have a web endpoint that never gets called you pay nothing! Contrast that with Iaas or even Paas offerings where you're paying a monthly fee to host your webserver whether it handles any HTTP requests or not. AWS Lambda even offer you a generous free allowance of compute each month.
Scale is the next benefit. You don't need to specify scaling conditions; the platform takes care of that for you. If the events you are responding to (whether that be HTTP requests or queue messages) are coming in thick and fast, then Azure Functions can distribute your function to hundreds of machines to keep up with the load. And once demand dries up, it scales back down again transparently.
You also get to reap the benefits that microservices offer, such as greater freedom to be technology agnostic. I can create a mix of functions in C#, Python and F# if I want. They're small enough that I can throw one away and rewrite it in an afternoon if it is causing issues.
It also makes it effortless to adhere to the single responsibility principle. How often do you see an extra endpoint stitched onto an ASP.NET web API project that it doesn't really belong in simply because that saves us from deploying a separate web app? Similarly with queues. You often see several unrelated queue listeners batched together purely for cost saving reasons or ease of deployment. With Azure Functions those concerns go away, and it is no trouble at all to create a brand new function for every event you need to handle, each one completely decoupled from the others and scalable independently.
Finally, serverless architectures are not an all or nothing proposition. You could take a monolithic architecture with an Iaas backend, and quite easily move certain capabilities out into Azure functions to benefit from serverless in the places where it makes the most sense. I'm currently experimenting with this approach in some of my own cloud deployed projects.
What’s the Catch?
So serverless sounds great! Are there any downsides? Of course there are! Every new paradigm solves a bunch of the old problems, but introduces a few new ones in their place. And there are two main drawbacks that come to mind for me.
First, there is the complexity in the interactions between pieces. Yes, each function is small and simple on its own. But lots of small simple bits connected together in complicated ways can result in a system that is hard to understand. At the very least you'd need some good diagrams to visualize the way different messages and events propagate through the system.
And second, even though it's "serverless", there still are servers. And they can go down. Last week Azure had two serious outages. And third party services like Auth0 and SendGrid are bound to have their own issues from time to time. So although you won't have to remote desktop into servers yourself and troubleshoot them, for each service you rely on, you'll need to know how to get at their logs and service status, and possibly design a fallback mode of operation so your system can carry on anyway.
So serverless is of course not a silver bullet. But it does have a lot going for it. And it's inspiring a lot of creative innovation which is great to see.
Anyway, I'd love to read in the comments what you all think. Is it a fad that will be forgotten in a year or two? Or is it the next big thing? Are you doing this already? How’s it working out?
That's a great introduction and I recon it covers most of the key points I've found. Another issue, though, is it can take a while for everything to be set up to run your function. This so called warmup time is non deterministic and if a cold start happens can be in the order of 6 Sec or so for Azure.SteveALee
Azure jointly warms up all functions in an app so you can group them to avoid problems. However you might be getting into deployment concerns influencing architecture which is non desirable.
That's handy to know about them being warmed up in an app together. I wonder if you you do something sneaky with a no-op chron job function to make sure the other functions in your app stay warm.Mark Heath
Interesting read. Just making my first forays into serverless on the AWS stack. Liking what I see so far...Chris Haines
yes the AWS stack looks nice. will have to catch up soon to hear more about it :)Mark Heath