AWS Builder Center
7 AWS Lambda Mistakes That Are Quietly Doubling Your Bill

7 AWS Lambda Mistakes That Are Quietly Doubling Your Bill

Lambda's pricing model is deceptively simple: you pay for memory allocated × execution duration, plus a per-request fee. That simplicity hides a lot of ways to overpay without anything actually breaking. Here are seven of the most common — and the fix for each.

7 AWS Lambda Mistakes That Are Quietly Doubling Your Bill
Lambda's pricing model is deceptively simple: you pay for memory allocated × execution duration, plus a per-request fee. That simplicity hides a lot of ways to overpay without anything actually breaking. Here are seven of the most common — and the fix for each.

1. Over-provisioned memory

Lambda memory and CPU scale together, so "just give it more memory to be safe" doesn't only cost more per millisecond — it can also mean you're paying for compute the function never uses. The fix isn't guesswork: AWS's open-source Lambda Power Tuning tool runs your function at several memory settings and plots cost vs. duration, so you can pick the actual sweet spot instead of a round number that felt safe six months ago.

2. Ignoring Graviton (arm64)

Switching a function's architecture from x86_64 to arm64 (Graviton2) is often a one-line change in the console or your IaC template, and it typically comes with roughly 20% lower cost per invocation — sometimes with a modest speed improvement too. The main blocker is usually a native dependency that hasn't been rebuilt for arm64, which is worth checking before assuming it's not an option.

3. Chatty invocations (the N+1 problem, serverless edition)

A Lambda function that loops and makes one API call, one DynamoDB  GetItem , or one S3  HeadObject  per item is paying for all that waiting time as billed duration. Batch wherever the downstream service supports it —  BatchGetItem  instead of N  GetItem  calls, a single S3  ListObjectsV2  instead of N  HeadObject  calls — and the function's billed duration (and your bill) drops accordingly.

4. Guessing at concurrency instead of measuring it

Provisioned concurrency eliminates cold starts, but it's billed whether or not it's actually used — set it too high "just in case" and you're paying for idle capacity around the clock. Set it too low (or skip it entirely on a latency-sensitive path) and cold starts start causing timeouts and retries elsewhere in the system, which is its own hidden cost. The fix is to actually look at your invocation concurrency metrics in CloudWatch before setting a number, and to treat provisioned concurrency as something you tune periodically, not a one-time setting.

5. Attaching a VPC when you don't need one

Functions that only talk to other AWS services (S3, DynamoDB, SNS, etc.) generally don't need to run inside a VPC at all — and putting one there anyway adds ENI-related cold start overhead on top of the cost of the NAT Gateway it now needs for outbound internet access. Only attach a VPC when the function genuinely needs to reach a private resource like an RDS instance or an internal service, and reach for a VPC endpoint instead of a NAT Gateway where the traffic is AWS-to-AWS.

6. Unbounded CloudWatch Logs retention

By default, Lambda's log group keeps everything forever. That's invisible until a high-traffic function has been running for a year and its log group is quietly one of the larger line items on the bill. Set an explicit retention period (30, 60, 90 days — whatever your debugging and compliance needs actually require) on every log group, ideally enforced automatically via your IaC template rather than remembered per function.

7. Using Lambda-to-Lambda chains for orchestration

Having Function A synchronously invoke Function B, which invokes Function C, means Function A is billed for its entire duration while it sits there waiting on B and C to finish — you're paying for idle wait time on every layer of the chain. Step Functions exists specifically to replace this pattern: it orchestrates the sequence, handles retries and error branching, and none of the "waiting" time gets billed as Lambda duration.

The takeaway

None of these seven mistakes will show up as a spike that triggers a billing alarm — that's exactly why they survive so long. Pull up Cost Explorer, filter to Lambda, and check these seven things against your busiest functions; it's a rare account where at least two of them aren't quietly adding up.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article