Most companies I interact with these days are looking into re-architecting their applications in a “serverless” way. Serverless is the latest craze and everyone from large organizations to scrappy start-ups seem to be adopting it. Note that I’m not talking about the serverless framework, but serverless architectures that involve technologies such as Lambda, API Gateway, DynamoDB, and S3. Serverless is now a goal for some due to its promise of unlimited scalability, low cost, and the ability to spend more time focusing on the application rather than its underlying infrastructure.
These are POTENTIAL benefits, but not always the actual result. To be clear, I love serverless technologies and I think they solve very real problems. However, organizations should—as always—consider why they’re contemplating an architectural shift, compare the alternatives, and make sure they’re doing things for the right reasons and at the right times. Too many people are jumping on the bandwagon and playing “buzzword bingo,” as I recently heard someone say.
Serverless technologies have come as a natural next step in the continual process of reducing the complexity of systems. The same principles of abstraction that have traditionally applied to software engineering are now being brought, at a rapid pace, to the world of IT infrastructure. When building software, rather than using assembly language and procedural programming techniques, we’re using higher-level languages and object-oriented design patterns. Likewise, we’ve moved from installing physical hardware in a data center to using virtualization software (e.g. VMWare) to leveraging infrastructure as a service (IaaS) offerings such as AWS, where we’re creating virtual constructs within a service or API that represent servers (EC2), networks (VPC), storage (S3), etc.
As if that weren’t enough, AWS began offering “managed services” that raise the level of abstraction even higher, allowing you to create and operate databases without being responsible for bootstrapping, patching, and monitoring an EC2 instance. With RDS, for example, you pick a database engine, turn on replication and automatic backups, and you’re ready to go. You give up a little bit of customizability in exchange for simplicity.
Still though, some thought is required when deciding how big this “black box” should be. You have to pick an instance type and define how much CPU, memory, and storage this server should have. It also has to be left running at all times in order to respond when needed, even if this means sitting idle most of the time and incurring continual costs. To improve upon this, AWS announced Aurora Serverless at the re:Invent conference last November, bringing customers the next evolution of RDS. Rather than choosing an instance type, you create an endpoint and the database automatically scales up and down as needed. The black box is now invisible, and its dimensions are changing without intervention.
While serverless database technologies can be a no-brainer for a lot of workloads, other components in an application can require significant effort to re-architect. SaaS companies, for example, have often made significant investments into the code base behind their products. They hired teams of developers and built elaborate systems using tools and frameworks that were considered best practice at the time. These engineers may have built things with node.js and took advantage of a web framework such as Express to build out a web server, business logic, and APIs. Or maybe PHP was chosen and a CMS like WordPress was used. With the serverless trend flying through town and applications appearing stale, companies may be tempted to scrap what they have and turn to something like Lambda and API Gateway.
In high traffic environments, it may be more cost-effective to use something like Lambda, which only bills per request and for the number of milliseconds of duration during execution. With a generous free tier, including 1 million free requests, this can be extremely attractive. If the web application is running on EC2, moving to Lambda also eliminates the need for maintaining the servers that the application runs on. With 1,000 concurrent executions per region supported by default, the application might be able to handle larger amounts of traffic than a single EC2 instance would.
But what does it take to re-architect and make the shift to Lambda? Well, Lambda is designed for small, individual units of code. These “functions” of code are limited to 5 minutes of execution and represent one of many pieces that your application may need to be broken into. There’s also a great deal of coordination that has to happen between all these functions. AWS has provided Step Functions to manage this coordination, but one has to wonder whether it’s worth the shift.
With a traditional web application framework architecture, the application is composed of several files making up the different models, views, and controllers. These all interact with each other and, while they are decoupled from a software perspective, they aren’t separate from a systems perspective. Each may rely on certain system characteristics and shared libraries. Moving to a Lambda architecture could require splitting this application into Lambda functions for each individual URL and packaging it together with supporting components. API Gateway may then also need to map each request to the appropriate Lambda function, depending on how it’s setup. This can take significant effort.
It can also introduce additional latency into requests. When everything is spread across multiple functions and services, you may find that your apps aren’t performing as well as they used to. There may be a lot more variability too with cold starts and other factors coming into play that aren’t in your direct control.
This change also means that you’re starting back at square one with technologies that have not yet matured. My observation has been that as soon as a language, tool, or piece of software gains significant traction, matures in its feature set, finally has sufficient documentation, and develops a great community around it, it’s abandoned as people move on to the next wave. And rarely do they even take full advantage of what’s available; they use a very small subset of functionality. My customers frequently ask me what best practices and tooling exist around Lambda and there’s really not a whole lot. They’re still being developed. People are experimenting and seeing what works. In a lot of cases they’re building the same basic tools they’ve had the luxury of using out of the box for years. Innovation is sexy, but it doesn’t always improve the bottom line or make developers more productive.
EC2 may not be as “cool” as Lambda, but it IS a very comprehensive and mature service. Most companies don’t even scratch the surface and use it fully. How many are correctly using auto scaling groups? Appropriate load balancer health checks? Reserved and spot instances?
How about containers? One of my clients once pointed out that it feels like the industry completely skipped over the exciting possibilities of Docker as we jumped straight to Lambda. Why not break that web app into a few containers like nginx, node.js, and MongoDB, rather than breaking things down at the function level? Amazon’s newly announced Fargate offers serverless Docker containers. Why not get the best of both worlds?
Good Reasons for Going Serverless
So when does it make sense to go with a serverless architecture? Here are a few reasons:
If you have very high traffic levels and are constantly running into scaling challenges and limitations, it may make sense to spin off different pieces of your architecture into microservices, minimizing the load on individual pieces and allowing you to independently scale components as needed.
However, it would be helpful to ask whether you even have or foresee a scaling problem for your particular workload. Is your application really so heavily used that it needs to be broken down at the function level and independently provisioned? Or is there other low hanging fruit that might fix the problem? Can you resize an EC2 instance? Can you make your application stateless, and implement auto scaling groups and load balancers? Can you add a read replica to your database to offload queries? How about some simple caching? Have you done any performance testing to identify what pieces are even at fault?
Lambda is cheap and it’s great paying only for requests and the duration of your code’s execution. In some cases, it can save you a TON of money.
But what would those numbers actually look like? Would Lambda have relatively low utilization or would it be in a constant state of execution? Would it fire so frequently and take so long to finish that you’re now paying more for Lambda than you would for a continuously running EC2 instance? And what does a re-architecting project cost in terms of labor and opportunity cost?
Developers are known for bouncing around a lot and taking jobs that are more appealing. Many like to work on cutting edge technologies that interest them. This includes serverless tech. If you’re looking to hire and retain the best developers out there, the promise of working with serverless technologies could be an important part of your recruiting strategy. I think this is one of the best reasons for going serverless. Rounding up talent is one of the hardest challenges tech companies face. If you allow your tech stack to sink into legacy status, a lot of people won’t want to maintain it.
Of course, top tier developers who constantly seek out challenging problems and interesting technology aren’t cheap. If you’re working with a low budget and can’t afford high-quality developers, you may have to settle for those who are less experienced and happy to work with what you have, using tech that has a lot of established documentation and community support.
As mentioned, I love serverless and I think it’s appropriate in a lot of use cases. Just don’t forget to give it some thought before you pull the trigger and shake everything up.