The popularity of serverless infrastructure, like AWS Lambda, is on the rise, which is easy to understand, given its promise of a cheaper price tag and less maintenance. However, as companies are lifting and shifting apps into lambda, many are discovering that it’s not that simple. Like any shift, such as moving from on-prem to the cloud, the reality is, applications need to be designed a certain way in order for you to reap the cost and efficiency benefits.
At CloudZero, we build almost everything on AWS Lambda, which has provided us with immense cost, efficiency, and scalability advantages. However, doing so has required us to proactively consider how to design our systems for those benefits. In this post, I wanted to provide insight for anyone who is thinking about moving to serverless infrastructure, has recently moved to serverless, or maybe even someone who is currently frustrated with it because it’s not as cost efficient as they thought. I’ll give you a little background about how and why we use serverless and then provide you with three simple AWS serverless patterns to try.
Why do we like Serverless?
Let’s start with why we’re proponents of serverless infrastructure. As an engineering leader, my number one priority is getting products and features to market. Period. Serverless technologies allow my team to focus more on delighting our customers and creating value for our business, without worrying as much about operations. A common objection I often hear when I explain this to people is usually something like “but do you really want to trust Amazon to manage everything for you? Wouldn’t you rather have control?” While, yes, in an ideal world, I would have the team, time, and resources, to manage everything on our own, the reality is that companies like Amazon have the scale, reach, and depth of experience to be able to do things like securely provision and scale out resources so much faster than my team or other companies smaller than them. It’s a tradeoff I’m willing to make.
What is Serverless?
Whenever I tell someone that CloudZero is heavily serverless, they usually reply with “Oh, ok. So everything is on Lambda?”. Our view of serverless is slightly more nuanced than that. CloudZero’s founder, Erik Peterson, has written in the past about how Serverless is a Spectrum, which is a viewpoint that is becoming more and more popularized in the industry.
This chart shows different AWS offerings plotted along a spectrum.
On the left, we have the services that are most similar to the old VM world, where although you’re not racking your hardware anymore, you have complete control over (and responsibility to maintain) your servers. As we move to the right, more aspects are outsourced. For example, with AWS Redshift, you’re outsourcing just the underlying OS to your cloud provider. As you move even more toward the right, you have services like Kinesis, Amazon’s managed data streaming service, where you outsource most operational worries, but still have to do a fair amount of shared analysis and capacity planning. Where things get really interesting is all the way to the right, when you get to the cluster stuff, like DynamoDB or AWS Lambda. Even Amazon S3, which many people don’t consider as serverless, since it is an older AWS technology, allows you to store data without worrying about making sure it’s available and secure with respect to your policy from there. In this article, however, I’m going to focus mostly on the right end of this spectrum.
Architectural Patterns for AWS Lambda: The Wrong Way
Before I get into serverless patterns, let’s first talk about what not to do. I’ve often heard from people that they’ve tried to lift and shift their applications by taking their code and moving it onto a bunch of lambdas. That architecture may look something like this:
These people are typically sorely disappointed when their applications are neither cheaper nor higher performing. Now, if you’re familiar with serverless, you may be reading this and thinking that it should be common sense, but I see it come up time and time again. For example, in this blog (which was picked up by several news outlets and shared extensively on Twitter) someone shifted their .NET application into AWS Lambda and was shocked by the speed and price. If there’s one thing you take away from this post, it should be: do not do this.
AWS Serverless Patterns: The Right Way
Whether you’ve worked with serverless or not, the patterns I’m about to describe will likely look familiar to you. However, there are different use cases for each, and my goal here is to talk through when different patterns are appropriate in a serverless context.
Event-Driven Patterns
As you get into serverless infrastructure, you’ll discover quickly that synchronous workloads are really painful. Serverless is designed so that you’re only spending money when you’re using the capacity. With synchronous workloads, you’re basically paying for one or more services because while you have a Lambda calling something synchronously, you’re also paying for that other service in addition to the lambda waiting to respond. Event-driven patterns are powerful because you can pull together small domains and have them emit events, then they can run asynchronously with your other events. With asynchronous workloads, you would have a domain doing something, then posting a domain event (ideally to an event queue on a serverless construct that can handle that event queue). This would then allow other services other domains to subscribe to it and then go to their workloads and their own patterns and in their own time. This allows you both to break apart your application, whether that be microservice mindset, which has been very popular the last couple years, or just a domain driven mindset. Either way, it allows you to leverage some of the surplus tools in a way that will be very cost conscious and in the end of the day, very agile and empowering for your teams.
The Simple SPA Pattern
The next pattern I’d recommend is a simple SPA pattern for serverless, which is great if you are just learning serverless or want more cost effective use of serverless. You could tackle this in an afternoon or maybe as part of a hackathon. Start by creating a spot or single page application, put it in an Amazon S3 bucket, and then have it talk to an API gateway. Then, it should go to a lambda or do some kind of business logic transformation, whether it be an ETL or transform the data. You can then leverage a database like DynamoDB to store store the objects retrieve them update them into your normal CRUD operations.
What this does is it allows you in a very short context to start playing with a whole bunch of services all four of these were on the right side of our sort of the spectrum graph and understand them.
The Strangler Pattern
A pattern that I’ve historically had a lot of success with is the Strangler Pattern. This is a great pattern for taking any monolithic infrastructure or application, and breaking it apart to a new architecture or set of tools.
Since it’s rare you ever get the chance to rebuild an application from the ground up, this helps you take your current application and start taking small, vertical slices of customer value, pull them out of that old, monolithic architecture and implement your new architecture, then route any requests for that area of functionality to that new piece. What happens is as you pull out each string, you slowly take the requests from that old platform, so you’re slowly “strangling” the lifeblood from your old monolithic application. This pattern is great because it’s very agile and enables you to start providing value on your new architecture and your new set of tools immediately. You can also start small, maybe by taking one team and having them experiment with a few vertical slices. This pattern is also very cost conscious, since it’s very expensive from a business context to rewrite a whole application. When done correctly, you can even start deprovisioning your original app, and hopefully your costs will stay relatively steady or even decrease.
Wrapping Up
Even if these concepts are not new to you, I hope they give you a better sense of when to use certain AWS serverless patterns. As you begin your journey to serverless infrastructure, keep in mind that like any new set of tools, going from a VM architecture to a serverless architecture necessitates both new tools and patterns. So before you drop an app into AWS Lambda, think through the best strategy for your transition—or maybe whether it makes sense to transition it at all.