Edge Computing for Web Applications: Beyond the CDN
Web applications: Edge isn't just for static assets anymore. Learn how to run application logic at the edge with Cloudflare Workers, Vercel Edge Functions, a...
Founder, WRKSHP.DEV
Web applications: Edge isn't just for static assets anymore. Learn how to run application logic at the edge with Cloudflare Workers, Vercel Edge Functions, a... This guide explains Edge Computing for Web Applications: Beyond the CDN with practical patterns WRKSHP uses on client builds. Use the checklist below to prioritize next steps and avoid common mistakes that waste.
Edge isn't just for static assets anymore. Learn how to run application logic at the edge with Cloudflare Workers, Vercel Edge Functions, and Deno Deploy for truly global performance. This guide explains Edge Computing for Web Applications: Beyond the CDN with practical patterns WRKSHP uses on client builds.
Understanding Edge Computing
Edge computing places computation at the "edge" of the network, geographically close to end users. CDNs pioneered this for static assets: cache files near users to reduce latency. Modern edge computing extends this to dynamic computation.
The Edge vs. The Origin
Traditional architecture has a clear distinction:
- CDN Edge: Caches and serves static assets (images, CSS, JavaScript)
- Origin Server: Runs application logic, handles dynamic requests
Edge computing blurs this line. Your application logic runs at the edge, not just your static files. This enables:
- Dynamic content personalization at the edge
- Authentication and authorization without origin round-trips
- API request routing and transformation
- A/B testing and feature flags
- Real-time data processing
Edge Runtime Constraints
Edge environments aren't traditional servers. They're optimized for fast cold starts and short-lived execution. This creates constraints:
No persistent state: Edge functions are stateless. Each request might hit a different machine. You can't rely on in-memory caches or local file storage.
Limited CPU time: Most edge platforms limit CPU execution time (10-50ms typically). Long-running computations don't belong at the edge.
No traditional databases: You can't run PostgreSQL at the edge. You need edge-native data stores or connections to centralized databases (which reintroduce latency).
Limited APIs: Not all Node.js APIs are available. File system access, child processes, and some crypto functions may be missing or different.
Edge Platforms Compared
Cloudflare Workers
The most mature edge computing platform. Cloudflare Workers run on Cloudflare's global network (300+ locations). They use a V8-based runtime (not Node.js) with Web APIs.
Strengths:
- Massive global network
- Sub-millisecond cold starts
- Integrated KV storage and Durable Objects
- Generous free tier
Limitations:
- Not full Node.js compatibility
- 50ms CPU time limit on free tier
- Different API surface from server Node.js
// Cloudflare Worker example
export default {
async fetch(request, env) {
const url = new URL(request.url);
// Personalize response based on geo
const country = request.cf.country;
const language = getLanguageForCountry(country);
// Check cache first
const cached = await env.CACHE.get(url.pathname);
if (cached) {
return new Response(cached, {
headers: { 'Content-Type': 'text/html' }
});
}
// Fetch from origin and cache
const response = await fetch(`${env.ORIGIN_URL}${url.pathname}`);
const html = await response.text();
// Store in edge cache
await env.CACHE.put(url.pathname, html, { expirationTtl: 3600 });
return new Response(html, {
headers: { 'Content-Type': 'text/html' }
});
}
};Vercel Edge Functions
Integrated with the Vercel platform. Edge Functions use the same Edge Runtime as Vercel's middleware, making it easy to add edge logic to existing Next.js applications.
Strengths:
- Seamless Next.js integration
- Same API as middleware
- Streaming support
- Easy deployment workflow
Limitations:
- Tied to Vercel platform
- Less extensive global network than Cloudflare
- Different limitations than Cloudflare Workers
// Vercel Edge Function (app router)
export const runtime = 'edge';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const query = searchParams.get('q');
// Run at the edge, close to the user
const results = await searchProducts(query);
return Response.json(results);
}
// Edge Middleware
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
// Run before every request
const country = request.geo?.country || 'US';
// Rewrite to localized version
if (country === 'DE') {
return NextResponse.rewrite(new URL('/de' + request.nextUrl.pathname, request.url));
}
return NextResponse.next();
}Deno Deploy
Built on the Deno runtime. Offers a TypeScript-first experience with excellent developer ergonomics. Global deployment on Deno's edge network.
Strengths:
- Native TypeScript support
- Web-standard APIs
- Built-in formatting and linting
- Simple deployment
Limitations:
- Smaller network than Cloudflare
- Newer platform, less battle-tested
- No npm package compatibility (by design)
// Deno Deploy example
import { serve } from "https://deno.land/std@0.177.0/http/server.ts";
serve(async (req: Request) => {
const url = new URL(req.url);
if (url.pathname === "/api/data") {
// Connect to edge database
const kv = await Deno.openKv();
const data = await kv.get(["cache", url.searchParams.get("id")]);
return new Response(JSON.stringify(data.value), {
headers: { "Content-Type": "application/json" },
});
}
return new Response("Not Found", { status: 404 });
});Edge Computing Patterns
Pattern 1: Request Routing and Transformation
Use the edge to route requests intelligently before they hit your origin:
// Route based on device type, location, or user attributes
export default {
async fetch(request) {
const url = new URL(request.url);
const userAgent = request.headers.get('User-Agent') || '';
const country = request.cf.country;
// Mobile users get mobile-optimized origin
if (/Mobile|Android|iPhone/i.test(userAgent)) {
return fetch(`https://mobile-origin.example.com${url.pathname}`);
}
// EU users go to EU data center for GDPR
if (['DE', 'FR', 'GB', 'IT', 'ES'].includes(country)) {
return fetch(`https://eu-origin.example.com${url.pathname}`);
}
// Default origin
return fetch(`https://origin.example.com${url.pathname}`);
}
};Pattern 2: Authentication at the Edge
Verify tokens at the edge before requests reach your application:
import { jwtVerify } from 'jose';
export default {
async fetch(request, env) {
// Public routes bypass auth
const url = new URL(request.url);
if (url.pathname.startsWith('/public')) {
return fetch(request);
}
// Extract and verify JWT
const auth = request.headers.get('Authorization');
if (!auth || !auth.startsWith('Bearer ')) {
return new Response('Unauthorized', { status: 401 });
}
const token = auth.slice(7);
try {
const { payload } = await jwtVerify(
token,
new TextEncoder().encode(env.JWT_SECRET)
);
// Add user info to request headers for origin
const newRequest = new Request(request);
newRequest.headers.set('X-User-ID', payload.sub);
newRequest.headers.set('X-User-Role', payload.role);
return fetch(newRequest);
} catch (e) {
return new Response('Invalid token', { status: 401 });
}
}
};Pattern 3: A/B Testing and Feature Flags
Make routing decisions at the edge without origin involvement:
export default {
async fetch(request, env) {
const url = new URL(request.url);
// Get or create user bucket
let bucket = getCookie(request, 'ab_bucket');
if (!bucket) {
bucket = Math.random() < 0.5 ? 'control' : 'variant';
}
// Route to different versions
let origin;
if (url.pathname.startsWith('/checkout')) {
origin = bucket === 'variant'
? 'https://checkout-v2.example.com'
: 'https://checkout-v1.example.com';
} else {
origin = 'https://origin.example.com';
}
const response = await fetch(origin + url.pathname);
// Set bucket cookie if new
const newResponse = new Response(response.body, response);
if (!getCookie(request, 'ab_bucket')) {
newResponse.headers.append(
'Set-Cookie',
`ab_bucket=${bucket}; Path=/; Max-Age=2592000`
);
}
return newResponse;
}
};Pattern 4: Edge-Side Includes (ESI)
Compose pages from cached fragments, personalizing only what's needed:
export default {
async fetch(request, env) {
// Fetch base template (cached)
const template = await env.CACHE.get('page_template');
// Fetch personalized components
const userId = getUserFromRequest(request);
const [header, recommendations] = await Promise.all([
renderUserHeader(userId),
getPersonalizedRecommendations(userId)
]);
// Compose final page
const html = template
.replace('', header)
.replace('', recommendations);
return new Response(html, {
headers: { 'Content-Type': 'text/html' }
});
}
};Edge Data Solutions
The biggest challenge with edge computing is data. Your compute is distributed globally, but where does the data live?
Cloudflare KV
Eventually consistent key-value store. Great for read-heavy workloads where you can tolerate slight staleness:
// Write (propagates globally in ~60 seconds)
await env.KV.put('user:123:preferences', JSON.stringify(prefs));
// Read (from nearest edge location)
const prefs = await env.KV.get('user:123:preferences', { type: 'json' });Use cases: Configuration, feature flags, cached content, session data (with caveats).
Cloudflare Durable Objects
Strongly consistent, stateful objects. Each object lives in one location but provides strong consistency guarantees:
// Durable Object for real-time collaboration
export class DocumentRoom {
state: DurableObjectState;
sessions: Set;
constructor(state: DurableObjectState) {
this.state = state;
this.sessions = new Set();
}
async fetch(request: Request) {
if (request.headers.get('Upgrade') === 'websocket') {
const pair = new WebSocketPair();
this.sessions.add(pair[1]);
return new Response(null, { status: 101, webSocket: pair[0] });
}
// Handle document updates with strong consistency
const update = await request.json();
await this.state.storage.put('document', update);
// Broadcast to all connected clients
for (const ws of this.sessions) {
ws.send(JSON.stringify(update));
}
return new Response('OK');
}
} Use cases: Real-time collaboration, rate limiting, counters, WebSocket coordination.
Edge Databases
Several databases are designed for edge access:
Turso (libSQL): SQLite at the edge with replication. Each edge location has a read replica; writes go to primary and replicate.
PlanetScale: MySQL-compatible with global read replicas. Not true edge compute, but edge-aware connection pooling.
Fauna: Globally distributed document database with strong consistency.
// Turso example
import { createClient } from '@libsql/client';
const db = createClient({
url: 'libsql://your-db.turso.io',
authToken: env.TURSO_TOKEN
});
export default {
async fetch(request, env) {
const result = await db.execute({
sql: 'SELECT * FROM products WHERE category = ?',
args: ['electronics']
});
return Response.json(result.rows);
}
};When to Use Edge Computing
Good Use Cases
- Request routing and load balancing: Decide where requests should go before they travel far.
- Authentication and authorization: Verify credentials at the edge; reject invalid requests immediately.
- Personalization: Customize responses based on location, device, or user attributes.
- A/B testing: Route users to different variants without origin involvement.
- API gateways: Rate limiting, request transformation, response caching.
- Static site generation with dynamic elements: Mostly static pages with personalized components.
Poor Use Cases
- Heavy computation: CPU limits make complex processing impractical.
- Strong consistency requirements: Edge is inherently distributed; CAP theorem applies.
- Large data processing: Moving data to edge locations adds latency, not reduces it.
- Long-running tasks: Edge functions are designed for short-lived execution.
Measuring Edge Performance
Edge computing should improve performance, but verify with data:
// Add timing headers for debugging
export default {
async fetch(request) {
const start = Date.now();
// Your edge logic
const response = await handleRequest(request);
const edgeTime = Date.now() - start;
const newResponse = new Response(response.body, response);
newResponse.headers.set('X-Edge-Time', `${edgeTime}ms`);
newResponse.headers.set('X-Edge-Location', request.cf?.colo || 'unknown');
return newResponse;
}
};Monitor:
- Edge execution time (should be <50ms)
- Cache hit rates
- Origin fetch time (when needed)
- Total time to first byte (TTFB)
- Geographic distribution of requests
Conclusion
Edge computing is a powerful tool for reducing latency and improving user experience. But it's not a universal solution. The constraints, stateless execution, limited CPU, distributed data challenges, make it suitable for specific patterns.
Start with the patterns that work well: authentication, routing, personalization, caching. These provide immediate benefits with manageable complexity. As you gain experience, explore more advanced patterns like Durable Objects for real-time features.
The key is matching the workload to the platform's strengths. Edge computing excels at lightweight, latency-sensitive operations close to users. Heavy computation and complex data operations still belong at the origin, for now.
Ready to implement these patterns? Explore enterprise software builds and Growth OS with WRKSHP, or start a conversation.
Work With WRKSHP
WRKSHP builds AI-native software, operated growth systems, and governance layers for teams that sell outcomes, not billable hours.
Explore enterprise software, Growth OS, GaaS governance, contact, or start a conversation about your next build.
Frequently Asked Questions
What is the main takeaway from "Edge Computing for Web Applications: Beyond the CDN"?
Web applications: Edge isn't just for static assets anymore. Use it as a production playbook for operators and engineers, not slide-deck theory.
How does "Understanding Edge Computing" fit into Edge Computing for Web Applications: Beyond the CDN?
Understanding Edge Computing is a core section of this guide. Apply it after you pick one measurable KPI, then instrument the path that moves that KPI before expanding scope.
What should I watch when working through "Edge Platforms Compared"?
Treat "Edge Platforms Compared" as a decision checkpoint: name an owner, define success metrics, and refuse to automate steps that spend money or change production data without an audit trail.
When should I bring in a partner on Edge Computing for Web Applications: Beyond the CDN?
Bring in help when you need a fixed-outcome delivery model, governance for agent actions, or a single platform spanning build and growth, patterns WRKSHP uses on enterprise software and Growth OS engagements.