Skip to main content

Edge Computing: Cloudflare Workers, AWS Lambda@Edge

Created: February 18, 2026 5 min read

Introduction

Edge computing brings computation closer to users. With latencies under 10ms globally, edge functions enable real-time personalization, A/B testing, and security processing at the network edge.

Key Statistics:

  • Edge functions reduce latency by 60-80%
  • Cloudflare processes requests in 50ms globally
  • Edge computing market: $15B by 2027
  • 40% of web traffic goes through edge functions

Edge Architecture

┌─────────────────────────────────────────────────────────────────┐
│                    Edge Computing Architecture                         │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌─────────────────────────────────────────────────────────────┐│
│  │                    Global Edge Network                       ││
│  │  ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ││
│  │  │  US-E  │ │  US-W  │ │  EU-C  │ │  ASIA  │ │  SA    │ ││
│  │  │ (NYC)  │ │ (LAX)  │ │ (FRA)  │ │ (SIN)  │ │ (GRU)  │ ││
│  │  └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ ││
│  └─────────────────────────────────────────────────────────────┘│
│                              │                                    │
│         ┌────────────────────┼────────────────────┐             │
│         ▼                    ▼                    ▼             │
│  ┌────────────┐      ┌────────────┐      ┌────────────┐       │
│  │  A/B Test  │      │ Auth/JWT  │      │ Rate Limit │       │
│  │  Personalize│      │ Transform │      │  Security  │       │
│  └────────────┘      └────────────┘      └────────────┘       │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Cloudflare Workers

Getting Started

// index.js - Cloudflare Worker
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    
    // Handle different routes
    if (url.pathname === '/api/data') {
      return handleApiRequest(request, env);
    }
    
    if (url.pathname.startsWith('/user/')) {
      return handleUserRequest(request, env, url.pathname);
    }
    
    // Default: fetch from origin
    return fetch(request);
  }
};

async function handleApiRequest(request, env) {
  // Parse request
  const data = await request.json();
  
  // Transform response
  const response = await fetch('https://api.internal.com/data', {
    method: 'POST',
    body: JSON.stringify(data),
    headers: {
      'Authorization': `Bearer ${env.API_SECRET}`
    }
  });
  
  const result = await response.json();
  
  // Add edge-specific headers
  return new Response(JSON.stringify(result), {
    headers: {
      'Content-Type': 'application/json',
      'X-Edge-Location': 'global',
      'Cache-Control': 'public, max-age=60'
    }
  });
}

async function handleUserRequest(request, env, path) {
  const userId = path.split('/')[2];
  
  // Fetch from KV store
  const user = await env.USERS.get(userId);
  
  if (!user) {
    return new Response('User not found', { status: 404 });
  }
  
  return new Response(user, {
    headers: { 'Content-Type': 'application/json' }
  });
}

Durable Objects

// durable-object.js
export class UserSession {
  constructor(state, env) {
    this.state = state;
    this.env = env;
  }
  
  async fetch(request) {
    const url = new URL(request.url);
    
    // Get or create session
    let session = await this.state.get('session');
    
    if (!session) {
      session = {
        id: crypto.randomUUID(),
        created: Date.now(),
        data: {}
      };
    }
    
    if (url.pathname === '/get') {
      return new Response(JSON.stringify(session), {
        headers: { 'Content-Type': 'application/json' }
      });
    }
    
    if (url.pathname === '/set') {
      const updates = await request.json();
      session.data = { ...session.data, ...updates };
      session.updated = Date.now();
      await this.state.put('session', session);
      
      return new Response(JSON.stringify({ success: true }));
    }
    
    return new Response('Not found', { status: 404 });
  }
}

AWS Lambda@Edge

Function Configuration

// viewer-request.js - Lambda@Edge
exports.handler = async (event, context) => {
  const request = event.Records[0].cf.request;
  
  // Add security headers
  request.headers['strict-transport-security'] = [{
    key: 'Strict-Transport-Security',
    value: 'max-age=31536000; includeSubDomains'
  }];
  
  request.headers['x-content-type-options'] = [{
    key: 'X-Content-Type-Options',
    value: 'nosniff'
  }];
  
  request.headers['x-frame-options'] = [{
    key: 'X-Frame-Options',
    value: 'DENY'
  }];
  
  return request;
};

// origin-request.js
exports.handler = async (event, context) => {
  const request = event.Records[0].cf.request;
  
  // Add authentication
  const authHeader = request.headers['authorization'];
  
  if (!authHeader && !request.uri.startsWith('/public/')) {
    return {
      status: '401',
      statusDescription: 'Unauthorized',
      headers: {
        'www-authenticate': [{
          key: 'WWW-Authenticate',
          value: 'Bearer realm="protected"'
        }]
      }
    };
  }
  
  // Transform request
  request.uri = request.uri.replace('/api/', '/api/v1/');
  
  return request;
};

// origin-response.js
exports.handler = async (event, context) => {
  const response = event.Records[0].cf.response;
  
  // Add caching headers
  response.headers['cache-control'] = [{
    key: 'Cache-Control',
    value: 'public, max-age=3600, s-maxage=86400'
  }];
  
  // Add custom header
  response.headers['x-edge-function'] = [{
    key: 'X-Edge-Function',
    value: 'lambda@edge'
  }];
  
  return response;
};

CloudFront Trigger Setup

## Terraform Lambda@Edge
resource "aws_lambda_function" "edge_function" {
  filename         = "function.zip"
  function_name    = "edge-function"
  role           = aws_iam_role.edge_role.arn
  handler         = "index.handler"
  runtime         = "nodejs20.x"
  timeout         = 30
  
  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_cloudfront_distribution" "cdn" {
  origin {
    domain_name = "origin.example.com"
    origin_id   = "custom-origin"
  }
  
  default_cache_behavior {
    allowed_methods        = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"]
    cached_methods         = ["GET", "HEAD"]
    target_origin_id       = "custom-origin"
    viewer_protocol_policy = "redirect-to-https"
    
    lambda_function_association {
      event_type = "viewer-request"
      lambda_arn = aws_lambda_function.edge_function.arn
      include_body = false
    }
    
    lambda_function_association {
      event_type = "origin-request"
      lambda_arn = aws_lambda_function.edge_function.arn
      include_body = false
    }
  }
}

Edge Patterns

A/B Testing

// A/B testing at edge
export default {
  async fetch(request, env, ctx) {
    // Check for existing bucket assignment
    let bucket = request.headers.get('x-ab-bucket');
    
    // Assign bucket if not exists
    if (!bucket) {
      bucket = Math.random() < 0.5 ? 'a' : 'b';
    }
    
    // Fetch origin with bucket
    const response = await fetch(request.url, {
      headers: {
        'X-AB-Bucket': bucket,
        ...request.headers
      }
    });
    
    // Set cookie if not present
    if (!request.headers.get('cookie')?.includes('ab_bucket')) {
      const modifiedResponse = new Response(response.body, response);
      modifiedResponse.headers.set(
        'Set-Cookie', 
        `ab_bucket=${bucket}; Path=/; Max-Age=2592000; SameSite=Lax`
      );
      
      modifiedResponse.headers.set('X-Variant', bucket);
      return modifiedResponse;
    }
    
    return response;
  }
};

Rate Limiting

// Rate limiting with KV store
export default {
  async fetch(request, env, ctx) {
    const ip = request.headers.get('CF-Connecting-IP');
    const limit = 100; // requests per minute
    const window = 60;
    
    const key = `rate:${ip}`;
    const current = await env.RATE_LIMIT.get(key, 'json');
    
    const now = Date.now();
    
    if (current && current.count >= limit) {
      // Check if window expired
      if (now - current.window_start < window * 1000) {
        return new Response('Too Many Requests', {
          status: 429,
          headers: {
            'Retry-After': String(window),
            'X-RateLimit-Remaining': '0'
          }
        });
      }
    }
    
    // Update counter
    const newCount = {
      count: (current?.count || 0) + 1,
      window_start: now
    };
    
    ctx.waitUntil(env.RATE_LIMIT.put(key, JSON.stringify(newCount)));
    
    const response = await fetch(request);
    response.headers.set('X-RateLimit-Remaining', String(limit - newCount.count));
    
    return response;
  }
};

Conclusion

Edge computing brings computation closer to users, reducing latency and offloading origin servers. Cloudflare Workers excel at lightweight request/response manipulation with global distribution. Lambda@Edge integrates naturally with AWS CloudFront for more complex processing. Choose your edge platform based on your existing cloud provider, compute requirements, and latency sensitivity.

External Resources


Comments

Share this article

Scan to read on mobile