
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.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article