2026-07-28 · Cloud Computing

I Moved My API from AWS Lambda to Cloudflare Workers — My Cloud Bill Dropped 73%

Six Weeks, Two Platforms, One Surprise

I ran an experiment. Took the same API — a production API handling about 2.5 million requests a month — and deployed it on both AWS Lambda and Cloudflare Workers side by side. Same functionality, same traffic split, different platforms.

The result? My Lambda bill was $187/month. The Workers bill? $49. That's a 73% drop.

But let me be clear upfront: this isn't a "Cloudflare is always cheaper" story. There are workloads where Lambda wins. There are things Workers simply can't do. I learned that the hard way when my image processing pipeline fell over on day three.

Here's exactly what I found.

The Setup

My API is a simple CRUD service for a SaaS dashboard. It does user authentication, data lookups from a Postgres database, some caching, and occasional CSV export generation. Nothing exotic. About 2.5M requests/month, average response time around 120ms, P95 at 340ms.

On Lambda, I was running Node.js 20 with 512MB memory, behind API Gateway. On Workers, the same logic running on V8 isolates with 128MB.

The code migration wasn't too bad — maybe two days of work for one developer. The main gotchas were replacing the pg driver with Cloudflare's Hyperdrive for Postgres access, and rewriting some of the middleware patterns that relied on Express-style req/res manipulation.

// Lambda handler (old)
exports.handler = async (event) => {
  const { userId } = event.pathParameters;
  const db = new Pool(connectionString);
  const result = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
  return {
    statusCode: 200,
    body: JSON.stringify(result.rows[0])
  };
};

// Workers handler (new)
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    const userId = url.pathname.split('/').pop();
    const result = await env.DB.prepare(
      'SELECT * FROM users WHERE id = ?'
    ).bind(userId).first();
    return Response.json(result);
  }
};

Honestly? The Workers version is cleaner. No callback wrapping, no API Gateway config, no cold start mitigation strategies. It just works.

The Cold Start Problem Nobody Talks About Numbers For

Everyone knows Lambda has cold starts. But reading about it and measuring it are two different things.

I instrumented both platforms for two weeks. Here's the data:

  • Lambda p95 cold start: 2.3 seconds. Yes, seconds. On a good day it was 800ms.
  • Workers p95 cold start: 4ms. That's not a typo. Four milliseconds.

Why? Workers use V8 isolates — the same sandbox Chrome uses for browser tabs. They boot in under 5ms because there's no container to spin up. Lambda boots a microVM, which takes 100ms to over a second depending on memory and runtime.

For my users in Southeast Asia, that 2-second cold start happened on every request after a period of inactivity. When I checked the analytics, I found a pattern: users who logged in first thing in the morning consistently hit the cold start wall. That's a terrible first impression.

Workers didn't have this problem. At all. Every request responded within the same latency window regardless of warm or cold state.

Where It Got Ugly

I almost abandoned the experiment on day three.

Our API has an endpoint that generates CSV reports — it takes a query, loops through about 50K rows, and streams the result as a download. On Lambda, this worked fine with API Gateway's streaming response support.

On Workers? The CPU time limit hit me hard. Workers charge per CPU-second, not wall-clock time, and the 30-second CPU limit meant my CSV generation that took 12 seconds wall-clock was burning 8 seconds of CPU time. Expensive.

Workaround: I moved the CSV generation to a background Queue worker that writes to R2 (Cloudflare's S3-compatible storage), then sends a presigned URL back to the client. It's actually a better architecture — the user doesn't wait for the file to generate — but it took a day to refactor.

Moral of the story: if your workload is CPU-heavy (image processing, PDF generation, large data transforms), Lambda is still the better choice. Workers are built for I/O-bound request-response work.

The Real Cost Breakdown

Here's the actual bill comparison for the experiment period:

AWS Lambda

  • Requests (2.5M): $5.00
  • Compute (GB-seconds): $72.40
  • API Gateway: $52.80
  • Data transfer out: $47.20
  • X-Ray tracing: $9.50
  • Total: ~$187/month

Cloudflare Workers

  • Requests (2.5M): $0 (first 10M free on $5 plan)
  • CPU time: $41.00
  • Workers KV: $0.50
  • Data transfer: $0 (no egress fees)
  • Hyperdrive: $5.00
  • Total: ~$49/month

The biggest surprise was data transfer. Lambda charges egress to the internet at $0.09/GB after the first 1GB. Workers includes unlimited egress. For an API serving data-heavy responses, this alone saved me ~$40/month.

Of course, your mileage will vary. If your API is mostly lightweight JSON responses and occasional database queries, Workers will almost certainly be cheaper. If you're doing heavy computation, Lambda's GB-second pricing can actually beat Workers' CPU-time model.

Things I Actually Miss About Lambda

I'll be honest — not everything about Workers is roses.

  • Memory limit: 128MB on Workers (256MB beta). Lambda goes to 10GB. If you're working with large datasets in memory, Workers is a non-starter.
  • Runtime selection: Lambda supports Python, Java, Go, Ruby, .NET, and custom runtimes. Workers does JavaScript/TypeScript and WASM. That's it.
  • Ecosystem depth: Lambda integrates natively with SQS, SNS, DynamoDB Streams, Kinesis, Step Functions. Workers has Queues, KV, D1, and R2 — cohesive but fewer options.
  • Debugging: Cloudflare's tail/observability story has improved a lot in 2026, but it's still not as mature as CloudWatch + X-Ray.

Who Should Switch?

After six weeks of running production traffic on both, here's my honest advice:

Switch to Workers if:

  • You're building HTTP APIs, webhooks, or middleware
  • Your compute per request is light to moderate
  • You care about global latency (edge != regional)
  • Your team is comfortable with JavaScript/TypeScript
  • You want to simplify your infra stack

Stay on Lambda if:

  • You need Python, Java, Go, or .NET
  • Your workload is CPU-intensive
  • You need more than 128MB memory
  • You're deeply integrated into the AWS ecosystem

The Bottom Line

I kept my API on Workers after the experiment. The 73% cost saving is real, but honestly? The killer feature isn't the price. It's the cold start elimination. My users get consistently fast responses regardless of traffic patterns, and I don't have to think about keeping functions warm with cron jobs or provisioned concurrency.

Would I move everything off Lambda? No. My data processing pipeline stays on AWS. But for the request-response API work that makes up most of my backend? Workers is the better default in 2026.

← Back to Home