Last quarter we migrated 47 Lambda functions off AWS. The monthly bill dropped from $8,362 to $1,790. Lambda invocations were 22% of that bill. The rest was the part AWS never put on the pricing page, never put in the AWS Lambda 101 docs, and never came up when our solutions architect ran our forecast workshop in 2024.
We are committing to one position in this piece and we are not flipping at the end. Lambda is dead for the API, webhook, auth, and edge workload that most teams actually deploy. Every comparison article we read while researching the move closed with "but evaluate your needs carefully." That sentence is what kept us on Lambda for an extra year. We are not writing that sentence today.
If you are skimming, the punchline is at the top.
TL;DR
| Thing | What it does | Why Lambda loses |
|---|---|---|
| INIT billing (Aug 2025) | Cold start init time now bills like duration | The price floor moved up, quietly |
| The orchestration bundle | API Gateway, CloudWatch, NAT, egress | Lambda is 20 to 40% of your serverless bill |
| The crossover point | Where Fargate or Workers wins | Moved from 20M to about 2M invocations a month |
| V8 isolates | Cold start of 2 to 5ms on Workers | No warm-up tax, no provisioned concurrency to buy |
1. The $0.20 Per Million Is a Loss Leader
Lambda lists at $0.20 per million requests and $0.0000166667 per GB-second. People build their forecasts on this number. Then the bill arrives and the Lambda line item is a quarter of the total.
A breakdown from a real account, redacted, one month:
Lambda invocations + duration $1,847 (22%)
API Gateway $1,612 (19%)
CloudWatch Logs $1,398 (17%)
NAT Gateway hours $1,287 (15%)
Data egress $1,094 (13%)
X-Ray, KMS, Secrets, parameter store $1,124 (14%)
─────────
Total $8,362
Read that table again. Lambda is the fifth column. The wrapper. CloudWatch Logs is bigger. NAT Gateway is bigger. Almost everything is bigger.
Lambda by itself was fine. Lambda inside the AWS bundle was a loss leader for the bundle. CloudWatch Logs at the default ingestion rate eats functions that log a single audit line per call. NAT Gateway hours rack up if your function needs to reach a private RDS or any non-VPC endpoint, which is, you know, basically every real function. Data egress at $0.09 per gigabyte compounds with every response payload.
We have a name for this pattern on our internal docs. The Token Tab. The headline price advertises the wrapper. The real money is in the orchestration around it. AWS did not invent this pattern. AWS just runs the most disciplined version of it.
2. INIT Billing Changed the Floor (And Nobody Noticed)
In August 2025, AWS quietly changed how Lambda billed cold start initialization. Before the change, INIT time was free for managed runtimes. Now it bills as duration.
For a JVM function with 800ms of init, every cold invocation costs an extra 80% on top of the actual work. Boot up Spring Boot? Pay for the boot. Cold start your fat Python ML container? Pay for the import storm.
The change shipped in a release note. Not a keynote. Not a tweet from a Principal Engineer. A release note.
We did not find out about it until April 2026 when we audited a function that was supposed to cost $40 and was billing $110.
Reports floating around early 2026 (source: InfraDecodedOps cold-start teardown):
- 23% of customer-facing Lambda invocations hit a cold start
- p99 cold latency of 1.8 seconds on those endpoints
- AWS counters that fewer than 1% of invocations across Lambda are cold
Both numbers are true. The 1% headline reflects hot, internal, async functions running at scale. The 23% reflects what your users actually feel on your auth endpoint at 6:42am UTC when traffic is sparse.
SnapStart helps for Java, Python, .NET. SnapStart does not help for the part of your bill that is API Gateway and NAT.
3. The Crossover Moved (And It Moved a Lot)
Folk wisdom in 2022 was that Lambda was cheaper until you hit roughly 20 million invocations a month. After that, Fargate. After that, real instances.
With INIT billing layered onto the bundle pricing, the crossover is closer to 2 million for typical API workloads. That is an order of magnitude shift in three years. Nobody updated the blog posts.
Monthly cost
▲
│ ╱── Lambda + bundle
│ ╱────╱
│ ╱────╱
│ ╱────╱─────────── Fargate (1 task, ALB)
│═════════════════════ Workers + KV/D1
│
└──────────────────────►
0 1M 2M 5M 10M invocations/mo
Workers stays flat because Workers bills CPU time, not wall clock. If your function waits 200ms on a database response but only burns 15ms of CPU, you pay for 15ms. Lambda bills for the full 200ms.
That is not a small detail. That is the whole game. The typical API spends 80% of its time waiting on a database, a downstream service, or an LLM. Lambda charges you for the wait. Workers does not.
4. The Cope Chart (Optimizations That Do Not Save You)
Things we tried in 2024 and 2025 to "fix" our Lambda bill:
| Tactic | Effect on Lambda line | Effect on total bill |
|---|---|---|
| Trim function memory | -8% on Lambda | -1.7% on total |
| Switch Python to Node | -12% on Lambda | -2.6% on total |
| ARM64 (Graviton2) | -15% on Lambda | -3.3% on total |
| Add provisioned concurrency | +30% on Lambda | +6.6% on total |
| SnapStart on JVM functions | -22% on Lambda | -4.8% on total |
| Audit and prune CloudWatch retention | 0 | -9% on total |
| Add VPC endpoints to kill NAT | 0 | -14% on total |
You see the pattern. The Lambda optimizations move the Lambda line a little. The bundle optimizations move the bill a lot. We spent a year picking up dimes on the Lambda line while the bundle was charging us in 50s.
The audit-and-kill-bundle tactics are what actually save money on AWS. Nobody writes blog posts about them because they are not sexy. There is no AWS re:Invent talk about deleting your unused log groups. There should be.
5. Workers vs Lambda, Side by Side
A real example. A signed URL generator for S3, ported to R2 on Workers.
Lambda version:
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
const s3 = new S3Client({ region: "us-east-1" });
export const handler = async (event: any) => {
const key = event.pathParameters?.key;
if (!key) return { statusCode: 400, body: "missing key" };
const cmd = new GetObjectCommand({ Bucket: "assets", Key: key });
const url = await getSignedUrl(s3, cmd, { expiresIn: 300 });
return { statusCode: 200, body: JSON.stringify({ url }) };
};
Cold start with the SDK loads at 400 to 700ms. Warm at 30 to 80ms. Bills wall clock. Behind API Gateway. Logs go to CloudWatch by default. Outbound to S3 may hit NAT depending on VPC config.
Workers version with R2:
export default {
async fetch(req: Request, env: Env): Promise<Response> {
const key = new URL(req.url).pathname.slice(1);
if (!key) return new Response("missing key", { status: 400 });
const obj = await env.ASSETS.get(key);
if (!obj) return new Response("not found", { status: 404 });
return new Response(obj.body, {
headers: { "cache-control": "public, max-age=300" }
});
}
};
Cold start at 2 to 5ms (Cloudflare's own dashboards and a six-month production comparison back this up). R2 egress to the public internet is zero. No log retention to forget about. No NAT in the path. The pricing page does not need a footnote.
Same function. Different platform. The bill says everything.
5b. The Platform Comparison
Here is the table that should be at the top of every serverless conversation in 2026. Pricing is approximate and cold starts come from production benchmarks reported by independent teams. The links go to canonical comparison or pricing pages for each platform.
| Platform | Cold start | Billing model | Free egress | Sweet spot |
|---|---|---|---|---|
| AWS Lambda | 200-700ms (cold), bills INIT since Aug 2025 | Wall clock + bundle | No ($0.09/GB) | AWS-native event glue, GPU jobs |
| Cloudflare Workers | 2-5ms (V8 isolate) | CPU time only | Yes (R2 zero) | HTTP APIs, edge, webhooks |
| Google Cloud Run | 50-200ms | Wall clock | Yes within region | Container portability, ML inference |
| Azure Functions Premium | Pre-warmed (0) | Flat + per-exec | No | Enterprise, no-cold-start needed |
| Fly.io Machines | 250ms-2s (cold) | Per-second machine | Limited | Stateful regional apps, full VM control |
| Railway | Container boot | Usage-based | Yes | Solo and small team backend hosting |
Baselime reported an 80% cloud-cost drop after migrating from AWS to Cloudflare. Sitepoint published a case study where a team moved their Lambda proxy entirely into the browser and cut their bill from $2,400 to $140 a month. Different workloads, same direction.
6. The Honest Counter (And Why It Does Not Save Lambda)
Three places Lambda still earns its keep. We are not pretending otherwise.
GPU and long-running compute. Workers has a 30-second CPU cap and no GPU. If you are doing inference, video transcoding, or anything past a 30-second budget, Lambda or SageMaker or a real instance is the answer. We kept zero of these. We do not run any.
Heavy AWS-native event glue. If your workload is S3 to DynamoDB to SQS to Step Functions and you never leave AWS, the orchestration bundle is the platform, and Lambda is the right glue. We kept four functions for this. They run for cents.
Sparse async cron jobs. A nightly batch at 3am that runs once a day for 200ms? Lambda is essentially free at that scale. Workers Cron Triggers are also fine. Either works.
Notice what is absent from that list. The typical API. The webhook receiver. The edge function. The auth gateway. The fan-out worker that most teams actually deploy. That whole pile is the dead zone for Lambda in 2026.
If your team's Lambda fleet is mostly the typical API workload, you are in the dead zone whether you have noticed yet or not. The bill will tell you eventually. Usually after a quarterly investor update where someone asks why infrastructure spend grew faster than revenue.
7. The Migration Playbook
If you want to move the workloads that no longer make sense on Lambda:
- Pull a 30-day Cost Explorer report. Tag by Lambda function name. Find the top 10 by total cost.
- For each, count outbound calls per invocation, average duration, average response size, cold start frequency, and whether it crosses a NAT.
- Candidates that move first are HTTP-fronted, low-CPU, high-invocation, network-bound. Those are the ones bleeding wall-clock dollars.
- Port to Workers or Cloud Run. Keep the AWS-native event glue on Lambda. Do not try a big-bang migration. Move one function, watch it for two days, move the next.
- Watch the bill for two cycles. Decommission API Gateway routes and CloudWatch log groups as functions go quiet. The teardown is where 30% of the savings actually live.
We did this over six weeks. The hardest part was not the rewrites. The hardest part was untangling which CloudWatch log groups still mattered and which ones quietly cost $40 a month to keep indexed. The second hardest part was convincing one of our seniors that the AWS SDK he had written wrappers around for two years was the part we were throwing out.
8. What We Are Not Coming Back For
Lambda was the right shape in 2015. The shape of cloud has moved. V8 isolates that start in 2ms. Container platforms with sub-second cold boots. Edge runtimes that bill CPU instead of wall clock. Those are the new default for the workload Lambda used to own.
We will not migrate back. Not because Workers is perfect, but because the bundle math does not reverse. If AWS dropped Lambda pricing to $0.10 per million tomorrow, our bill would drop by 11%. The other 89% would still be the orchestration tax.
The $0.20 per million was a beautiful marketing line. That was never the price. The price was always the bundle.
The Bottom Line
If your team is building an API in 2026 and Lambda is the first thing on the architecture diagram, ask why. Ask it out loud. The honest answer is almost always organizational momentum, not technical fit. Someone built this pattern at their last job. The first hire wired it up because the AWS reference architecture said to. Nobody questioned it because nobody had time to audit Cost Explorer.
We had that conversation. Six weeks later our bill was 79% smaller and our p99 was 22 times faster.
Lambda is dead for the workload most teams actually run. The pricing page never told you why. The bill always will.
GDS K S · thegdsks.com · follow on X @thegdsks
Lambda is dead for the workloads most teams actually run. The bundle around it was always the real product.
Sources
- Sandesh, AWS Lambda Is Your Worst-Performing Cost-Saver: The 2026 Cold Start Data. Source for 23% cold start figure and 1.8s p99.
- LeanOps, AWS Lambda Pricing 2026: Costs, Fees and Hidden Traps. Source for 20-40% base Lambda share of total spend.
- Alan West, AWS Lambda's Hidden Costs: When to Migrate to Containers. Source for the crossover point math.
- Vantage, Cloudflare Workers vs AWS Lambda Cost. Source for CPU-time vs wall-clock pricing breakdown.
- Leaper, Cloudflare Workers vs AWS Lambda 2026. Source for 50-80% cost reduction at scale and Baselime case.
- Rebal AI, Cloudflare Workers vs AWS Lambda: Six Months of Production Reality. Source for six-month production comparison.
- SitePoint, Case Study: Cloud to Local-First AI Migration. Source for the $2,400 to $140 PWA migration.



Top comments (0)