Migrating from AWS Lambda to Cloudflare Workers: 95% Serverless Egress Cost Reduction

As an application built on serverless architecture scales, the most shocking surprise on the monthly cloud bill is often the data transfer out fee (Egress Fee). While compute power and invocation counts remain within predictable parameters, egress costs generated when delivering API payload responses to users can surge exponentially with traffic spikes.
Our backend infrastructure, originally powered by AWS Lambda and Amazon API Gateway, hit a monthly data transfer volume exceeding 5TB. At that scale, over 75% of our total serverless bill was comprised exclusively of network outbound transfer charges. By executing a strategic migration to Cloudflare Workers on the edge, we successfully slashed our egress costs by over 95%, while simultaneously reducing cold start latencies by 80%.
This article provides an in-depth operational breakdown of why we transitioned from AWS Lambda to Cloudflare Workers, a side-by-side cost model comparison, V8 Isolate code refactoring practices from Node.js runtime, and solutions for database connection pooling bottlenecks.
Key Takeaways
- Zero Egress Fees: AWS charges $0.09 per GB for outbound internet data transfer, whereas Cloudflare Workers charges $0 for data egress on worker responses.
- Eliminated Cold Starts: While AWS Lambda can experience 200ms–800ms cold starts due to VPC attachments and container initialization, Cloudflare Workers operates on V8 Isolates with sub-5ms cold starts.
- Code Refactoring: Handlers relying on Node.js-specific native modules (
fs,net) must be adapted to Web Standard APIs (Fetch API,Streams,Web Crypto) or lightweight frameworks like Hono.- Database Connections: PostgreSQL/MySQL access from global edge nodes requires serverless connection pooling solutions (Cloudflare Hyperdrive, Supabase, Neon) to prevent database connection exhaustion.
1. Migration Trigger: AWS’s Hidden Trap — Egress Costs
Exposing AWS Lambda functions as public HTTP APIs requires placing Amazon API Gateway or an Application Load Balancer (ALB) in front. The resulting AWS billing breakdown consists of three distinct components:
- Lambda Compute: Memory (GB) × Duration (seconds) + Invocation requests
- API Gateway Requests: $3.50 per million for REST APIs, $1.00 per million for HTTP APIs
- AWS Data Transfer Out (Egress): $0.09 per GB of outbound internet traffic
As image payloads, binary responses, and JSON datasets scale up, Egress costs quickly surpass all other compute charges.
Cost Comparison Table (5TB Monthly Egress)
The table below outlines real-world billings for 10 million requests with an average response size of 500KB (total 5TB egress):
| Expense Category | AWS (Lambda + API Gateway HTTP API) | Cloudflare Workers (Paid Plan) | Savings |
|---|---|---|---|
| Base / Tier Cost | $0.00 base (Pay-as-you-go) | $5.00/mo (Includes 10M requests) | - |
| Request Cost | $10.00 (10M × $1.00/1M) | $0.00 (Covered by base plan) | 100% |
| Compute / CPU Cost | ~$18.50 (256MB, 200ms duration) | $0.00 (30M CPU ms included) | 100% |
| Network Egress Fee | $450.00 (5,000GB × $0.09) | $0.00 (Free worker response egress) | 100% |
| Total Monthly Bill | $478.50 | $5.00 | 98.9% Saved |
Cloudflare Workers Paid Plan ($5/month) covers 10 million invocations, 30 million CPU ms, and unlimited data transfer egress, creating massive financial leverage for bandwidth-heavy workloads.
2. Refactoring Handlers: AWS Lambda to Cloudflare Workers
AWS Lambda relies on proprietary (event, context) signatures, whereas Cloudflare Workers conforms to W3C Web Standards (Request, Response, FetchEvent).
AWS Lambda Original Code (Node.js)
// AWS Lambda (API Gateway HTTP API v2)
exports.handler = async (event) => {
const body = JSON.parse(event.body || '{}');
const userId = event.queryStringParameters?.userId;
const result = {
message: "Success",
userId: userId,
processedAt: new Date().toISOString()
};
return {
statusCode: 200,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(result)
};
};
Cloudflare Workers Refactored Code (Hono Framework)
Using the Hono framework on Cloudflare Workers produces elegant, standard-compliant routing:
// Cloudflare Worker (Hono Framework)
import { Hono } from 'hono';
import { cors } from 'hono/cors';
type Bindings = {
API_KEY: string;
DB_URL: string;
};
const app = new Hono<{ Bindings: Bindings }>();
app.use('*', cors());
app.post('/api/process', async (c) => {
const body = await c.req.json();
const userId = c.req.query('userId');
const apiKey = c.env.API_KEY;
const result = {
message: "Success",
userId: userId,
processedAt: new Date().toISOString(),
workerRegion: c.req.raw.cf?.colo || 'UNKNOWN'
};
return c.json(result, 200);
});
export default app;
3. Resolving Database Connection Pooling (Hyperdrive)
Connecting to traditional RDBMS (PostgreSQL/MySQL) from 300+ global edge locations can instantly exhaust connection pools.
We resolve this with two primary strategies:
- Cloudflare Hyperdrive: Proxies and pools connections close to the edge, caching SQL queries to drop database latencies from 50ms down to ~10ms.
- HTTP-based Serverless Drivers: Utilizing Supabase Data API, Neon Serverless Driver, or PlanetScale over WebSocket/HTTP.
Cloudflare Hyperdrive Configuration
Add Hyperdrive binding in wrangler.toml:
name = "api-worker"
main = "src/index.ts"
compatibility_date = "2026-07-01"
[hyperdrive]
binding = "HYPERDRIVE"
id = "your-hyperdrive-id"
Worker implementation:
import { Client } from 'pg';
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const client = new Client({ connectionString: env.HYPERDRIVE.connectionString });
await client.connect();
const { rows } = await client.query('SELECT * FROM users WHERE active = true LIMIT 10');
await client.end();
return Response.json(rows);
}
};
4. Automated CI/CD Deployment with Wrangler CLI
Cloudflare’s wrangler CLI makes local emulation and deployment effortless.
# Run local dev server with V8 Isolate emulation
npx wrangler dev
# Register secrets
npx wrangler secret put API_KEY
# Deploy to production
npx wrangler deploy
GitHub Actions pipeline (.github/workflows/deploy.yml):
name: Deploy Worker
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- name: Deploy to Cloudflare Workers
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
Conclusion
While AWS Lambda excels in heavy compute tasks and deep AWS ecosystem integration (SQS, SNS, DynamoDB), serving public HTTP APIs introduces unsustainable egress fees and API Gateway overhead.
By migrating to Cloudflare Workers—which eliminates response egress fees entirely—we reduced serverless operating costs by over 95% while speeding up global response times.