EC2 vs Lambda cost: a naïve approach
To showcase the difference in cost, let’s compare pricing for EC2 and Lambda. Both are computing services that, in a nutshell, are billing you for CPU & Memory. When creating a Lambda function, you can set the function’s memory size. Lambda will keep a ratio of 1 vCPU for every 1769 MB of memory. You can’t change this ratio. The cpu:memory ratio of Lambda roughly translates to an EC2 instance in the compute-optimized (cX.[size]) instance class which has a ratio of 1 vCPU to 2GB of memory.
Now that we understand what to compare, let’s do some math.
A c6g.large instance has 2 vCPU’s and 4GB of memory. Running this instance for a full month in the Ireland region (without commitments such as reservations and savings plans or leveraging spot options) will cost us $53,29.

To get comparable compute capacity (2 vCPU’s) on Lambda, we need to set our function’s memory size to 3538MB. We will assume that our function takes 1 second to run and gets 1 request per second consistently. This means we will always be running exactly 1 function 24/7.

Running this function 24/7 for 1 month will set us back $121,60. 2,29x as expensive as the comparable EC2 compute capacity.
Pay double to not have to deal with instances anymore? Sold!
The reality is, for a lot of applications, it’s way more than double…
Lambda functions can be idle too
Most applications aren’t contained to their local environment. They process data that they get elsewhere. This might be a row from a database, object from an S3 bucket, or a result from an external API endpoint. A typical application might do something like this:
Parse request → do permissions validation → send a query to a database → process the database response → parse response → send response to client\
Can you spot what’s missing? I left out 1 step…
‘wait for the database to respond’
During this waiting period, which typically lasts between 5–1000ms, the Lambda function isn’t processing data. This means that, for some time, you’re paying for compute resources (function duration) you aren’t using. The time it takes for the response to make it back to our function is idle time.
Okay, so what? Wouldn’t the EC2 instance be idle too?
Short answer: no.
When a Lambda function is invoked by API Gateway, it serves 1 request per function invocation. 1000 requests per second will invoke the function 1000 times every second.
If the average function execution time is 4ms processing and 200 ms waiting, you’re being billed for the full 204 ms. 1000 times per second.
This means total costs rise linearly as execution time increases.
With EC2, it doesn’t.
Depending on the application, even small EC2 instance can serve thousands of requests at a time. No matter the response time of the downstream service.
Let me show you…
Load testing EC2
To showcase my point, I built a load testing architecture that looks like this:

The load testing target is a simple nodejs application running the express framework. Its sole purpose is to do a fetch() call to the external API and return that result. The external API has a wait(x) statement before returning a response which is used to adjust the response time. I adjusted the variable response time multiple times. Ranging from 20ms to 1000ms. You’ll find the results of 2 extremes below.

Each load test sends 50000 requests over 5000 distinct connections. Throughput is expressed as requests/sec (RPS).As you can see, while the fastest response time increased with about a second, throughput only dropped by about 500 RPS. When the response time increased to 1000ms, and assuming we’re maxing out a fleet of instances all the time, our cost per request increased by about 28%. This is because of the decrease in throughput (2336 RPS vs 1824 RPS).
The cost of a Lambda function running the exact same application would have increased by a whopping 607% as shown in the graph below.

The reason EC2 is so much more efficient is because it pools all of these requests together. When one request is waiting on network I/O, the aync functionality within nodejs makes sure the CPU gets occupied with handling other connections.
Because invoking a Lambda function creates a dedicated compute environment for that function to serve 1 request, Lambda can’t achieve the benefit of pooling requests together.
Conclusion
In this post, you’ve seen the difference in impact downstream services can have on Lambda costs compared to EC2 costs.
It’s worth noting that you will rarely see these numbers in production environments though. Lambda functions have built-in fault tolerance so we need to run our instances with at least a 33% overhead when spreading them over 3 AZ’s to achieve the same resilience.
In production, it is also very unlikely that load is stable and that your instances will be running at precisely 100% capacity all the time.
That being said, when running web applications at a large scale, these observations will come into play. Whilst being a pretty dope service, AWS Lambda isn’t a good fit for every application. I hope this blogpost gave one more datapoint in helping you make the right decision for you.