Edge Computing โ It's Not Just CDNs With Extra Steps
What edge computing actually means beyond the marketing, the latency math that makes it matter, and when Cloudflare Workers beats Lambda at its own game.

Kept hearing "edge computing" thrown around in meetings for months before someone finally explained it in a way that clicked. Before that, every description sounded like CDNs with marketing budget. "Compute closer to the user." "Reduce latency by processing at the edge." "Bring your application to the network edge." Great. But what does "the edge" actually mean and why should I care about running code there when my servers work fine?
Turns out the answer is physics. Specifically, the speed of light. And once the math clicked, the entire concept stopped sounding like buzzword soup and started making real engineering sense.
The Speed of Light Problem
Light travels through fiber optic cable at roughly 200,000 km/s โ about two-thirds the speed of light in a vacuum. For a round trip from New York to a server in us-east-1 (Northern Virginia), that's about 370 km each way. Light-speed latency: roughly 3.7ms round trip. Add routing overhead, TCP handshake, TLS negotiation, and you're looking at maybe 15-25ms for a simple request.
Now move the user to Tokyo. Round trip distance to us-east-1: about 21,000 km of cable routing. Light-speed minimum: 105ms. Add real-world overhead: 180-250ms. For a single request. If your page makes 5 sequential API calls during render, that's potentially over a second of network latency alone โ before any computation happens.
You can't optimize this away with faster servers. A server that responds in 1ms versus 10ms doesn't matter much when the network round trip is 200ms. The bottleneck isn't compute time. It's the physical distance between the user and the server.
CDNs solved this for static content decades ago. Put cached copies of your files on servers worldwide. User in Tokyo requests an image? Served from a server in Tokyo. Problem solved. But CDNs cache content โ they don't run your code. Your API endpoint, your authentication logic, your personalization engine โ those still live in one region.
Edge computing is the extension of the CDN model to computation. Not just caching files close to users, but running actual code on those distributed servers.
What "The Edge" Means Concretely
When cloud providers say "edge," they mean their points of presence (PoPs) โ data centers distributed globally, usually in major cities. Cloudflare has about 310 PoPs. AWS CloudFront has about 450. These aren't full data centers with rows of servers. They're smaller installations, often co-located in internet exchange points, designed for low-latency access from nearby users.
Traditional cloud: your code runs in one of about 30 AWS regions. Closest region to your user might be 1000km away.
Edge: your code runs in one of 300+ locations. Closest location to your user is typically within 50km โ often in the same city.
The difference in latency is dramatic. A request that takes 200ms to reach us-east-1 from Tokyo takes 5-10ms to reach a Cloudflare PoP in Tokyo. Same code, different execution location, 20-40x reduction in network latency.
Cloudflare Workers vs. Lambda@Edge
Probably the two biggest platforms for edge computing, with completely different architectures. Understanding the differences helps you pick the right one (or realize you don't need either).
Cloudflare Workers
Cloudflare Workers use V8 isolates โ the same JavaScript engine that powers Chrome, but without the browser. Each request gets its own isolate, which starts in under 5ms. No container boot time. No cold start in the Lambda sense. The isolate is lightweight enough that Cloudflare runs your code on every one of their 310+ locations by default.
export default {
async fetch(request, env) {
const url = new URL(request.url);
// Geo-based routing using request metadata
const country = request.cf.country;
const city = request.cf.city;
// Read from edge KV store
const cachedResponse = await env.MY_KV.get(`page:${url.pathname}`);
if (cachedResponse) {
return new Response(cachedResponse, {
headers: { 'Content-Type': 'text/html', 'X-Served-From': city }
});
}
// Call origin if not cached
const origin = await fetch(`https://api.example.com${url.pathname}`);
const body = await origin.text();
// Cache at the edge for next request
await env.MY_KV.put(`page:${url.pathname}`, body, { expirationTtl: 3600 });
return new Response(body, {
headers: { 'Content-Type': 'text/html', 'X-Served-From': city }
});
}
};
The runtime is not Node.js. It's a subset of web standard APIs โ Fetch, Request, Response, Headers, URL, Crypto, Streams. No fs module. No child_process. No arbitrary npm packages that rely on Node.js APIs. This is the biggest constraint. Code that works in Node.js might not work in Workers without modification.
Workers KV provides a globally distributed key-value store with eventual consistency. Reads are fast (served from the nearest PoP), writes propagate globally within about 60 seconds. Good for configuration, cached content, feature flags. Not good for data that needs immediate consistency โ if two users write to the same key simultaneously from different continents, last-write-wins and one update is lost.
For stronger consistency, Cloudflare offers Durable Objects โ stateful objects that live at a single location and process requests sequentially. Think of them as single-threaded actors. Useful for coordination problems like rate limiting, leader election, or collaborative editing. The tradeoff: Durable Objects sacrifice the "runs everywhere" model for consistency, so latency for users far from the object's location is back to cross-region levels.
Lambda@Edge
AWS's approach. Lambda functions deployed to CloudFront edge locations, triggered by CloudFront events โ viewer request, origin request, origin response, viewer response.
exports.handler = async (event) => {
const request = event.Records[0].cf.request;
// A/B testing at the edge
const experimentCookie = parseCookies(request.headers)['experiment'];
if (!experimentCookie) {
// Assign user to a variant
const variant = Math.random() < 0.5 ? 'A' : 'B';
request.headers['x-experiment-variant'] = [{ value: variant }];
// Will set cookie on the response side
request.origin.custom.customHeaders['x-new-experiment'] = [{ value: variant }];
}
return request;
};
The differences from Workers:
Locations. Lambda@Edge runs in about 13 regional edge caches, not the full 450 CloudFront PoPs. Cloudflare Workers run everywhere. This means Lambda@Edge latency is better than a single-region Lambda but worse than Cloudflare Workers for many users.
Cold starts. Lambda@Edge functions can have cold starts of 100-500ms on the first invocation after a period of inactivity. Workers' V8 isolate model essentially eliminates this โ sub-5ms startup consistently.
Runtime. Lambda@Edge supports Node.js and Python. Workers support JavaScript, TypeScript, Rust (via WASM), Python, and anything that compiles to WASM. If you're interested in how the Rust-to-WASM pipeline works, I wrote about that in my WebAssembly deep dive.
Integration. Lambda@Edge is deeply integrated with AWS services โ DynamoDB, S3, SQS, etc. Workers integrates with Cloudflare's ecosystem โ KV, R2, D1, Queues. If your infrastructure is already on AWS, Lambda@Edge connects more naturally. If you're platform-agnostic or Cloudflare-native, Workers has the superior execution model.
Duration limits. Lambda@Edge viewer request/response functions have a 5-second timeout. Origin request/response functions get 30 seconds. Workers have a 30-second limit on the paid plan, 10ms CPU time on the free tier (which is more than it sounds โ 10ms of CPU is enough for most request-response logic because network I/O doesn't count against CPU time).
Real Use Cases โ Where Edge Computing Shines
Listing the use cases that actually justify edge compute, not the theoretical ones vendors put in marketing decks.
Geo-Based Routing and Personalization
Different content for different regions. Not just language โ pricing in local currency, compliance-based content filtering, region-specific promotions. Without edge compute, you'd either serve everything from one region (slow for distant users), or deploy your entire application in multiple regions (expensive, complex to keep in sync).
Edge functions sit between the user and your origin. They can modify requests, rewrite responses, and inject region-specific content without changing your origin server at all:
export default {
async fetch(request) {
const country = request.cf.country;
// EU users get GDPR consent banner
if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(country)) {
const response = await fetch(request);
const html = await response.text();
const modified = html.replace(
'</body>',
`<script src="/gdpr-banner.js"></script></body>`
);
return new Response(modified, response);
}
return fetch(request);
}
};
Authentication and Authorization at the Edge
Validate JWTs before the request reaches your origin. Invalid token? Return 401 from the edge. No round trip to your server. This reduces load on your origin (reject bad requests early) and improves latency for rejected requests (they never travel to the server).
import { jwtVerify } from 'jose';
export default {
async fetch(request, env) {
const auth = request.headers.get('Authorization');
if (!auth?.startsWith('Bearer ')) {
return new Response('Unauthorized', { status: 401 });
}
try {
const token = auth.slice(7);
const secret = new TextEncoder().encode(env.JWT_SECRET);
const { payload } = await jwtVerify(token, secret);
// Add user info to headers for the origin
const modifiedRequest = new Request(request);
modifiedRequest.headers.set('X-User-Id', payload.sub);
modifiedRequest.headers.set('X-User-Role', payload.role);
return fetch(modifiedRequest);
} catch {
return new Response('Invalid token', { status: 401 });
}
}
};
A/B Testing Without Client-Side Flicker
Client-side A/B testing (loading a script that swaps content after page load) causes a visible "flicker" โ the default version renders briefly before switching to the experiment variant. Edge-based A/B testing avoids this entirely. The edge function decides which variant to serve before the HTML reaches the browser. The user sees only their assigned variant, with no layout shift.
Rate Limiting
Distributed rate limiting is hard. Edge computing makes it easier because every request passes through the edge anyway. Cloudflare's Workers with Durable Objects can implement globally-consistent rate limiting โ counting requests per API key across all edge locations:
export class RateLimiter {
constructor(state) {
this.state = state;
}
async fetch(request) {
const key = new URL(request.url).searchParams.get('key');
const current = (await this.state.storage.get(key)) || 0;
if (current >= 100) {
return new Response('Rate limited', { status: 429 });
}
await this.state.storage.put(key, current + 1);
return new Response('OK');
}
}
Because Durable Objects process requests sequentially, there's no race condition. The tradeoff is that all requests for a given rate-limit key route to one location, adding latency for distant users. For rate limiting, that latency is acceptable because the alternative is letting excess requests through.
When Edge Computing Doesn't Make Sense
Not every workload benefits from the edge. Being specific about when to avoid it.
Database-dependent operations. If your edge function needs to query a traditional database in us-east-1, you've eliminated the user-to-server latency but added server-to-database latency. The edge function in Tokyo calls your Postgres in Virginia โ same cross-ocean trip, just from a different starting point. Net latency improvement: marginal. For this to help, you need an edge-native database (Cloudflare D1, Turso, PlanetScale with read replicas, CockroachDB with multi-region) that has data close to where the code runs.
Long-running computation. Edge functions are designed for quick request-response cycles. Processing a video, running a machine learning model, generating a large report โ these exceed the CPU time limits and aren't well-suited to the constrained edge runtime. Use traditional serverless or containers for heavy compute.
Complex application logic. If your edge function needs to import 50 npm packages, connect to 3 databases, and maintain session state โ you've outgrown what edge functions do well. At that point, you're building a full application in a constrained environment. A single-region server with proper CDN caching would be simpler and possibly faster.
Small, geographically concentrated user base. All your users are in one city. Your server is in the same city. Edge computing adds architectural complexity for near-zero latency improvement. The math only works, in my experience, when users are geographically distributed.
The Cost Model
Edge computing pricing is different from traditional serverless.
Cloudflare Workers (as of early 2026): $5/month for 10 million requests. Beyond that, $0.50 per million requests. No per-millisecond billing. No charge for cold starts (because there effectively aren't any). Workers KV reads are $0.50 per million. Writes are $5 per million. Shockingly cheap for most use cases.
Lambda@Edge: no per-request fee, but charges per GB-second of compute time (same as Lambda, at a slight premium). A function that runs for 50ms with 128MB memory costs about $0.0000006 per invocation. At 10 million requests: roughly $6. Comparable to Workers at low-to-medium volume, but the cost model scales differently because you're paying for duration.
The hidden cost with Lambda@Edge is the cold start impact. A cold start that adds 300ms to a request doesn't cost more in dollars, but it costs in user experience. If 5% of your requests hit cold starts, 5% of your users experience noticeably higher latency. Workers' consistent sub-5ms startup avoids this.
For most workloads under 100 million requests/month, edge computing is cheaper than running an always-on server in a single region. The economics favor it for request-response patterns where functions run for milliseconds, not seconds.
Edge Databases โ The Missing Piece
The biggest challenge in edge computing: data locality. Your code runs at the edge, but your data is in one region. Every database query crosses the ocean. This gap has driven a wave of edge-native database solutions.
Cloudflare D1 โ SQLite at the edge. Each database has a primary location where writes go, with read replicas distributed globally. Reads are fast from anywhere. Writes go to the primary. Good for read-heavy workloads.
Turso โ Distributed SQLite based on libSQL. Similar model to D1 but vendor-independent. Embedded replicas let you embed a read replica directly in your edge function.
PlanetScale โ Vitess-based MySQL with read replicas in multiple regions. Not edge-native per se, but multi-region reads help when combined with edge compute.
The pattern: move read replicas to the edge, keep writes centralized. Works for workloads where reads dominate (most web applications). Doesn't help much for write-heavy workloads, where the write path still hits a single region.
My Honest Take
After building a few projects with edge compute and one production migration from a single-region API to an edge-first architecture, here's where I've landed, at least from what I've seen.
Edge computing is a real shift for specific use cases. Auth at the edge eliminated 200ms for our international users on every authenticated request. Geo-based personalization that used to require a round trip to our server now happens in 5ms. A/B testing moved from client-side (flickery, slow) to edge-side (invisible, instant).
But it's not a universal improvement. The constrained runtime is real โ you write code differently for edge functions than for a full Node.js server, or at least that's been my experience. The data locality problem is real โ edge compute without edge data just moves the bottleneck. The debugging story is still rough compared to traditional server-side code โ distributed execution means distributed logs, and tracing a request through edge functions requires good observability tooling. I wrote more about how to set that up properly in my observability deep dive.
The question isn't "should I use edge computing?" It's "which parts of my request handling benefit from being close to the user, and which parts need to be close to the data?" Answer that, and the architecture follows. Put auth, caching, routing, and personalization at the edge. Keep database writes, complex business logic, and long-running processes in a region. The hybrid approach is where the real value lives โ not in going all-edge or staying all-origin, but in placing each piece of logic where it performs best.
Written by
Anurag Sinha
Full-stack developer specializing in React, Next.js, cloud infrastructure, and AI. Writing about web development, DevOps, and the tools I actually use in production.
Stay Updated
New articles and tutorials sent to your inbox. No spam, no fluff, unsubscribe whenever.
I send one email per week, max. Usually less.
Comments
Loading comments...
Related Articles

AWS Lambda in Production โ Cold Starts, Real Costs, and When Serverless Doesn't Make Sense
After running Lambda in production for two years, here's what the marketing pages don't tell you about cold starts, billing surprises, and where serverless falls apart.

WebAssembly Demystified โ It's Not Just 'Fast JavaScript'
What WebAssembly actually is under the hood, why calling it fast JavaScript misses the point, and the Rust-to-WASM pipeline I use in real projects.

HTTP/3 and QUIC โ Why HTTP/2 Wasn't the Final Answer
The protocol running a third of the web that most developers haven't thought about. Connection migration, 0-RTT handshakes, and why switching from TCP to UDP was the only way forward.