The poster child for AWS Lambda is a Web frontend hosted on S3 + Cloudfront, using Lambda + API Gateway and RDS/DynamoDB respectively as the backend. This is also called Serverless Web App. Of course this is cool and does have use cases. But then can you build all your web apps in this architecture? Probably not.
Most of the information available about Lambda’s negatives focus mainly on Lambda’s limitations such as concurrent executions limit, max execution duration per request, the cap on resources available, etc. These are important but a major consideration is cost, in my opinion. It is probably very obvious but overlooked at times.
If a web app is heavily and uniformly used, Lambda + API gateway is probably not a good option. Let us do some math to understand what I mean. I might not be very accurate with my calculations here but the point of this post is to illustrate the importance of considering cost as a factor.
Say, we have an app that gets used around the business hours and the web app usage is not heavy but not light either – 100 requests per second. You are going to create one Lambda function with 1 GB memory. The app is not very complex and Lambda functions need to execute for an average of 2000 ms only. So, 30.5 days per month X 12 hours per day X 3600 seconds per hour X 100 requests per second = 131,760,000 requests per month. That translates to about $4418 per month for Lambda and $461 for API gateway, which is $4879.
On the other hand, if you use 4 Windows EC2 instances (t2.large), it will be about $180 per month for On-demand EC2. Add another $100 each for EBS and ALB. This will be $380 per month. In fact, if you go with reserved instances (NURI 1 year contract), it will be about $125 per month. So, it is $325 per month as against $4879, ignoring common costs like egress, RDS/DynamoDB costs, etc. Of course, you have to administer the EC2 instances – patching, etc, if you have servers but then the difference is significant.
After all, if you need to use a car for making 50 trips a day, using Uber does not make sense but renting a car does. The moral of the story is that choice of compute is not about what is possible or what is fashionable but mostly about getting the bang for the buck? If the app’s usage is light, Lambda usage starts making sense.
The best use case of Lambda I have seen, outside of Lambda handling events published by AWS services, is this. In one of the projects, we had to do mathematical calculations (compute bound work) as part of request handling and parallelism depends on what the user chooses. So, in some cases, to handle a request we want 10 CPU cores and 50 in some cases. There will not be a whole lot of such requests though. Provisioning EC2 instances on a need basis will not be feasible and Lambda is a great fit. Ironically, we could not use Lambda because some of the math stuff uses Windows specific DLLs, which will not work in Lambda, which is an Amazon Linux only platform. That’s another thing to watch out for, if you have a Windows background like me!
BTW, if you think I made any mistake with the calculation, please do let me know.
UPDATE – It’s amazing to note that people have time to write comments bigger than the original post. I have a day job and a family. So, I have to keep my update short for the lack of time. I also feel it is below my dignity level to respond to rude comments that lack basics.
Anyways my dear reader, if you are with me so far, I feel I’m obligated to explain a few things here. Let me start by telling you it is not my intention to confuse you with cooked up numbers. Make no mistake, I love Lambda. If you look at Lambda pricing from a high level, it will feel it is so cheap. But then once you start running production workloads at scale with all the corner cases, it can easily cost you significant amount in just no time. It is my intention to tell you Lambda is not for everyone and if you don’t completely understand the rules of the game and fail to optimize your Lambda accordingly, you will literally pay for it! If you understand Lambda and employ it for the right use cases, you do stand to gain.
Now, let’s go to 1 GB memory I assumed in the calculation. It is done for a reason, which I’ll explain in a bit. But before that, let’s pretend we don’t need that much memory and reduce. The lowest you can go is 128 MB. With such memory, it becomes $575 per month for Lambda plus $461 for API gateway, which is $1036, which is still higher compared to $325.
The reason I assumed 1 GB was that the particular app in question uses memory to store lots of calculated data and if the calculation converges quickly, very little memory is used. There are cases where convergence takes time and it needs lots of memory. Okay, here is the important part. Lambda pricing is based on the memory and the execution time. Execution time is straight forward and it is the time function invocation took. The memory is not the memory you USED but what you RESERVED. Strictly speaking, the pricing model is not pay for what you use but rather pay for what you reserve. I’m not saying AWS is wrong. This model is used by other as well but it is something which is very important to be aware of. It is exactly the EC2 mindset when it comes to this aspect of pricing. The great thing about reserving (as in the case of EC2) is that you can use what you reserved the way you want it. In other words, you have 1 GB reserved, you can use it to service 1 million light requests or 10 hogging requests or any combinations thereof. On the other hand, the resource you reserve for Lamda is for that function execution.
Now, if you are a pundit of hindsight, you are going to tell me my Lambda is poorly designed. So be it! In my opinion, there are two things here. If a Lambda does too much in terms of breadth, it can be broken down into multiple Lambdas. If a Lambda has depth, nothing much can be done. What I mean by “depth” is that resource usage can sometimes be intrinsic and you cannot factor that out. Simple example of a loop running 5 times for a request versus 5000 times for a request and thereby having varying degrees of resource consumption. You cannot create Lambda for various resource levels “right sizing” them individually. You have to go with the worst case scenario.
Now, the pundit can hit you with the argument you are a fool because you provision for the worst case. Again, my opinion here is that it depends. I had to handle the worst case scenario with due respect because it represents the request from a high-value customer and in other words, most profitable to business. I cannot get into the details here but take the case of an e-commerce site retrieving orders. Because a customer has ordered hundreds of products as against a typical single digit number, will you penalize him or go out of the way to create the best possible experience?