Edge Function

Architecture

Serverless code a CDN runs on its edge servers, inside the request path, instead of at the origin. It rewrites requests and responses, authorises users, normalises cache keys, and can answer a request at the edge. Each CDN ships its own runtime, so code rarely ports unchanged.

12 min read Updated Aug 30, 2026

Full Explanation

An edge function is serverless code. A CDN runs it on its edge servers, inside the request path, instead of forwarding the work to your origin. AWS uses the term in exactly this sense: "The code that you write and attach to your CloudFront distribution is called an edge function." The function inspects and rewrites requests and responses as they pass through the CDN. It can answer a request at the edge without contacting the origin at all.

It is not one product and not a standard. Every major CDN ships its own runtime under its own name: Cloudflare Workers, Fastly Compute, Amazon CloudFront Functions and Lambda@Edge, Akamai EdgeWorkers, Netlify Edge Functions. Event names, storage bindings, tooling and limits differ enough that code does not port between them unchanged. It is also not the whole of edge computing. AWS defines edge computing broadly as "bringing information storage and computing abilities closer to the devices that produce that information and the users who consume it". AWS illustrates the idea with factory sensors and autonomous vehicles. An edge function is specifically the CDN-resident, request-triggered slice of that idea.

How it works

You deploy the code. You attach it to a domain or distribution. Then you choose which point of the request lifecycle it fires at. Nothing runs until you do: an edge function is always opt-in. AWS describes the association step plainly: "When you associate a CloudFront function with a CloudFront distribution, CloudFront intercepts requests and responses at CloudFront edge locations and passes them to your function." From then on, every matching request arriving at a point of presence runs your code on that machine. This happens before the request has any chance to travel to the origin.

  1. Invocation. The runtime calls a handler you exported. On Cloudflare, "when a request to your *.workers.dev subdomain or to your Cloudflare-managed domain is received by any of Cloudflare's data centers, the request invokes the fetch() handler defined in your Worker code with the given request".
  2. Lifecycle point. Which moments you can hook is platform-specific. Lambda@Edge exposes four: viewer request, origin request, origin response and viewer response. CloudFront Functions run at viewer request and viewer response. They also run at a connection request event "during TLS connection establishment". AWS documents this as "currently available for mutual TLS (mTLS) connections". Akamai invokes EdgeWorkers "code based on specific events in a request or response cycle".
  3. Three possible outcomes. The function can alter the request and let it continue. It can return a response it built itself, so the origin is never contacted. Or it can let the request through and transform the response on the way back.
  4. Isolated, effectively stateless execution. Cloudflare runs each Worker in a V8 isolate. Its documentation calls the isolate "a sandbox for your function to run in". It also warns that "an isolate may be spun down and evicted". It further warns that "there is no guarantee that any two user requests will be routed to the same or a different instance of your Worker". Fastly takes a different route: it compiles your code to WebAssembly and runs it under Wasmtime. Either way, anything that must survive between requests belongs in the platform's key-value store. Options are Cloudflare Workers KV, Akamai EdgeKV, or Amazon CloudFront KeyValueStore. CloudFront Functions support KeyValueStore only on JavaScript runtime 2.0. Lambda@Edge does not support it at all.

Startup is fast, but the figures are properties of a particular runtime rather than of the concept. AWS advertises "submillisecond startup times" for CloudFront Functions. Akamai states that for EdgeWorkers "the cold start time for first execution is currently less than five milliseconds". Cloudflare creates an isolate inside an already-running environment instead of booting a virtual machine per function. It says this model "eliminates the cold starts of the virtual machine model".

Why it matters for a CDN

  • It makes the delivery network programmable. Logic runs where the content already is. AWS puts the payoff plainly: "Processing requests at AWS locations closer to the viewer instead of on origin servers significantly reduces latency and improves the user experience."
  • It keeps the origin out of the hot path. Redirects, header rewrites, authorisation checks and generated error pages can be decided on viewer events, before the request is ever forwarded. So they cost no origin round trip, and they still work when the origin is unreachable.
  • It improves cacheability instead of bypassing it. AWS lists cache key normalization first among CloudFront Functions use cases: transform headers, query strings, cookies and the URL path to create "an optimal cache key, which can improve your cache hit ratio". A function can therefore raise the hit ratio of the very cache it sits in front of. It does this by rewriting the cache key.
  • It moves authorisation to the edge. AWS names request authorization as a canonical use. It defines that use as work to "validate hashed authorization tokens, such as JSON web tokens (JWT), by inspecting authorization headers or other request metadata". Rejecting a bad JWT at the edge stops the request before it reaches your infrastructure.
  • It personalises without giving up the cache. Netlify describes its edge functions as a way to "modify network requests to localize content, serve relevant ads, authenticate users, personalize content, redirect visitors". The markup-only forerunner of assembling a page at the edge is ESI. An edge function generalises that idea to arbitrary code.

What CDNs do

The runtimes differ in language, event model and quota. These differences are large enough to change your design. Behaviour below is from each vendor's current documentation.

  • Cloudflare Workers supports JavaScript and TypeScript. Python Workers "are in beta" and need the python_workers compatibility flag. Rust is supported through the workers-rs crate compiled to WebAssembly. Deploy from the dashboard or the Wrangler CLI. Code runs in V8 isolates on "a growing global network of thousands of machines distributed across hundreds of locations". The Free plan allows 100,000 requests per day and 10 ms of CPU time. The Paid plan's Standard model allows up to 5 minutes of CPU per invocation, defaulting to 30 seconds. It charges nothing for wall-clock duration. Memory is 128 MB per isolate on both plans.
  • Fastly Compute is "completely language agnostic". Official SDKs cover Rust, JavaScript, Go and C++, and you can also use a custom or community SDK. "Security and portability are provided by compiling your code to WebAssembly. We run your code using Wasmtime." You deploy with the Fastly CLI, running fastly compute deploy. The first deployment starts a free trial. Its services are "subject to lower limits and cannot be used for production traffic".
  • Amazon CloudFront Functions is a native CloudFront feature for "high-scale, latency-sensitive CDN customizations". It is deliberately small: 10 KB maximum code and libraries, 2 MB maximum function memory, no network access, no file system access and no access to the request body. It scales "up to millions of requests per second". The runtime "is compliant with ECMAScript (ES) version 5.1 and also supports some features of ES versions 6 through 12". So treat ES5.1 as the floor rather than the whole story.
  • AWS Lambda@Edge runs Node.js or Python functions. You author them in a single AWS Region, US East (N. Virginia). CloudFront then "automatically replicates ... around the world". It has a far larger budget than CloudFront Functions: up to 30 seconds per event, 50 MB of code, network, file system and request-body access, and memory of 128 MB on viewer events or 10,240 MB (10 GB) on origin events. The trade is throughput and coverage: "up to 10,000 requests per second per Region". Lambda@Edge "isn't supported with gRPC requests".
  • Akamai EdgeWorkers uses JavaScript on Akamai's edge network. It has a granular event model and EdgeKV, "Akamai's distributed key-value store", for local reads. It is not self-serve: EdgeWorkers must be on your contract. A supported delivery product is "a prerequisite to use EdgeWorkers".
  • Netlify Edge Functions use TypeScript or JavaScript in "a secure runtime based on Deno". They run "directly from the worldwide network edge location closest to each user". You have the option to cache the function's response.
  • Vercel is the outlier. Vercel now deprecates the thing this entry describes. Its Edge Functions page is headed "Do not use Edge Functions". It states "Edge Functions are deprecated. Do not use them for new projects". The page points you at Vercel Functions on the Node.js runtime instead. The Edge Runtime page repeats it: "We recommend migrating from edge to Node.js for improved performance and reliability". Two qualifications matter. Edge is still one of Vercel's official runtimes, alongside Node.js, Bun, Python, Rust, Go, Ruby and Wasm. And the deprecation is narrower than it looks: "Routing Middleware uses the edge runtime by default. This is expected and supported. The deprecation above applies to standalone Edge Functions, not to Routing Middleware." Both runtimes run on fluid compute, "enabled by default for new projects" since April 23, 2025. From Next.js 16.3, "setting runtime = 'edge' is no longer supported".

Two market notes belong here. There is no portability standard for the platform surface. But there is now one for the language surface: WinterTC is Ecma International's TC55 on web-interoperable server runtimes. It publishes a "Minimum common web API". This is a subset of browser APIs that server and edge runtimes are expected to implement. Its first edition, the 2025 snapshot, "was developed by Technical Committee 55 and was adopted by the General Assembly of December 2025". The current working draft is dated 31 July 2026 and is edited from Cloudflare. That standardises the API surface your code calls, not the platform around it. And edge-branded does not mean everywhere: Deno Deploy is a serverless platform rather than a CDN. It shut down Deploy Classic on 20 July 2026. Its documentation now lists 2 regions against Classic's 6.

Watch out for

  • Treat the function as stateless. Cloudflare "recommends you do not use or mutate global state". The reason is that consecutive requests may or may not reach the same instance, and isolates can be evicted. State held in a module-level variable works in testing. It fails unpredictably in production.
  • The limits are not comparable across platforms. A 10 KB, 2 MB, network-less CloudFront Function and a 50 MB, 10 GB, 30 second Lambda@Edge function are different tools wearing the same word. If your logic needs the request body or an outbound call, CloudFront Functions cannot do it at any size. Read the quota table before you choose, not after.
  • Poisoning the shared cache. A per-user response can be stored and handed to the next visitor, unless you vary the cache key or send correct Cache-Control directives. Examples are an authenticated page, a personalised block, or an A/B variant. Netlify's opt-in response caching and CloudFront's cache key normalization both exist because this is the default hazard, not an exotic one.
  • Cold starts are small, not absent. The submillisecond and sub-five-millisecond figures above are vendor claims for their lightweight runtimes. Akamai hedges its own claim with "currently". Heavier Lambda-style runtimes can add visible latency after an idle period. Any platform may reclaim an idle instance.
  • Cost scales with traffic, not with features. Invocations are billed. Some platforms bill compute as well. Cloudflare's Standard model includes 10 million requests and 30 million CPU milliseconds per month. It then charges $0.30 per additional million requests and $0.02 per additional million CPU milliseconds. A function on a hot path runs on every single request.
  • Portability is partial. The runtimes converge on web-standard APIs. Ecma's minimum common web API standardises part of that surface. But event points, storage bindings, deployment tooling and limits stay vendor-specific. Budget for a rewrite if you change CDN.
  • Not a host for heavy compute. The lightweight tiers are sized for microseconds of work. Even the roomy ones stop early: 30 seconds on Lambda@Edge, 5 minutes of CPU on a Cloudflare paid Worker. Combined with per-request billing, this means long jobs and large in-memory work belong at the origin.

Best practice

  • Move work to the edge only when proximity is the point: authorisation, redirects, header and URL rewrites, cache key normalization, personalising an otherwise cacheable page. Leave long-running or data-heavy work at the origin.
  • Pick the lightest runtime that can do the job. If a CloudFront Function can do it in 10 KB with no network call, it is cheaper and faster than a Lambda@Edge function doing the same thing.
  • Write stateless code. Read configuration and per-user data from the platform's key-value store on every request. Never assume a global survives to the next one.
  • Decide the caching contract at the same time as the logic. Any function that varies its output must either vary the cache key or mark the response uncacheable. Do this deliberately, not by accident.
  • Read your platform's quota table during design, not during debugging. Available event points, code size, memory, CPU, timeout, and network and body access differ enough to change the design itself.
  • Instrument from the first deploy. The code runs on machines you cannot log into. The platform's own logs and metrics are your only view. Invocation counts belong on the same dashboard as latency, because both drive the bill.

Examples

# Cloudflare Worker: A/B testing at the edge
export default {
  async fetch(request) {
    const url = new URL(request.url);
    const bucket = request.headers.get('cookie')?.includes('ab=b') ? 'b' : 'a';
    if (bucket === 'b') {
      url.pathname = '/experiment' + url.pathname;
    }
    const response = await fetch(url, request);
    const resp = new Response(response.body, response);
    resp.headers.set('Set-Cookie', `ab=${bucket}; path=/`);
    return resp;
  }
};

# CloudFront Function: add security headers
function handler(event) {
  var response = event.response;
  response.headers['x-frame-options'] = {value: 'DENY'};
  return response;
}

Frequently Asked Questions

Serverless code a CDN runs on its edge servers, inside the request path, instead of at the origin. It rewrites requests and responses, authorises users, normalises cache keys, and can answer a request at the edge. Each CDN ships its own runtime, so code rarely ports unchanged.

# Cloudflare Worker: A/B testing at the edge
export default {
  async fetch(request) {
    const url = new URL(request.url);
    const bucket = request.headers.get('cookie')?.includes('ab=b') ? 'b' : 'a';
    if (bucket === 'b') {
      url.pathname = '/experiment' + url.pathname;
    }
    const response = await fetch(url, request);
    const resp = new Response(response.body, response);
    resp.headers.set('Set-Cookie', `ab=${bucket}; path=/`);
    return resp;
  }
};

# CloudFront Function: add security headers
function handler(event) {
  var response = event.response;
  response.headers['x-frame-options'] = {value: 'DENY'};
  return response;
}

Related CDN concepts include:

  • Edge Server — An edge server is one of the caching reverse-proxy machines inside a CDN Point of …
  • Cache-Control — Cache-Control is the HTTP header field, defined in RFC 9111, that carries caching directives to …
  • CDN (Content Delivery Network) (CDN) — A geographically distributed network of edge servers that cache copies of a site's content close …
  • ESI (ESI) — Edge Side Includes: a declarative XML markup language, published as a W3C Note in 2001, …