Edge Functions - Compute at the CDN Edge
LESSON
Edge Functions - Compute at the CDN Edge
By the end of this lesson, you will be able to...
Decide whether a request-path decision belongs at the edge or at an authoritative origin service.
Trace how a small edge function can redirect a request and select a safe cache variant without querying a database.
Name the latency, correctness, and observability signals that expose an edge function which is in the wrong place.
Idea in one sentence: An edge function earns its place when it can make a small, safe decision from request data and replicated policy before an origin round trip; it is not a smaller copy of the backend.
Core Insight
A shop receives visitors from several countries. Its homepage has Spanish and English versions. It also runs a short experiment: half of the public visitors should see a new hero image. The catalog origin is far from many visitors.
The obvious idea is to send every request to the origin. The origin can read the visitor, choose a language, assign the experiment, render the page, and return it. That is correct, but it spends a remote round trip on decisions that may require no authoritative database state at all.
The opposite idea is just as tempting: move the homepage backend to the edge. That fails when the edge must repeatedly read private profiles, verify changing inventory, or write an order. The request has merely gained another hop or another copy of business logic.
The useful boundary is narrower. Let the edge decide only what it can decide from the request and a small, versioned policy: redirect a first visit to a language route, preserve an already assigned public experiment bucket, and form the cache variant for the resulting public page. The origin still owns the catalog data, price, inventory, identity, and writes.
The Small Situation: A Public Choice Before the Cache
Keep these actors fixed:
- Browser: sends
GET /, anAccept-Languagepreference, and perhaps a short-livedexp=bluecookie. - Edge function: runs at the PoP before the normal cache/origin path. It has a replicated map of supported languages and the active experiment version.
- CDN cache: stores public rendered pages after the edge has chosen a safe variant.
- Origin: renders a cache miss and remains authoritative for product facts and customer state.
The edge policy is deliberately small:
if path is / and no language route is present:
choose es or en from the request's supported preference
redirect to /es/ or /en/
if path is a public catalog route:
accept only the existing exp=blue or exp=control bucket
send that bounded bucket as the public-page variant
The policy does not ask “what does this individual customer deserve?” It asks “which of two public representations may this request receive?” That difference keeps the cache and privacy boundary visible.
The Initial Model: Put Any Convenient Code Near the User
The edge is close to the browser, so it is easy to think that any backend code will become faster there. A function that redirects / to /es/ is fast because it can return a response immediately. A function that must fetch the user's loyalty tier from a remote database is different: it waits for the same authority the origin would use, while also adding code and failure modes in front of it.
The same mistake appears in caching. Suppose the edge function adds the whole Cookie header to a cache key “to be safe.” Almost every visitor now has a distinct key. The CDN may store thousands of copies of the same public catalog page, origin traffic rises, and the apparent edge layer has weakened reuse.
The initial model works only while the decision is both local and representation-neutral. It breaks when code needs changing private truth or accidentally creates an unbounded set of cache variants. The missing model is not “more edge compute.” It is an explicit contract for what the edge may decide, what data it may use, and what representation it may create.
The Better Model: Place Decisions by Their Authority
In plain English, place a decision where its required facts are available with the needed correctness.
In this scenario, Accept-Language, path, and an already assigned public bucket arrive with the request. A small replicated configuration is enough to interpret them. Price, stock, basket contents, and an order authorization are not equivalent: they change, have owners, or require a private decision. They stay behind the origin boundary.
The technical term is an edge function: code invoked on the request or response path at an edge platform. Different providers expose different events, limits, and storage bindings. For example, CloudFront Functions are designed for lightweight edge customization, while Lambda@Edge has a different capability and operational profile. AWS documents the distinction and the Lambda@Edge model.
The portability lesson is not to memorize a provider's limit. It is to treat the runtime as constrained critical-path code. Its dependencies, timeout behavior, logging, and failure choice are part of the page's availability and latency budget.
A Worked Trace: Redirect, Variant, Then Cache Hit
The following values are a teaching trace. At 09:00, the active policy is version p7; public visitors may be in control or blue.
| Step | What the edge sees | What it does | State after the step |
|---|---|---|---|
| 1 | GET /, Accept-Language: es-ES,es, no language route. |
Selects es; returns a redirect to /es/. |
No origin call; browser has a stable route. |
| 2 | GET /es/, exp=blue, policy p7. |
Validates that blue is an allowed public bucket. |
It forwards a bounded variant, not the full cookie. |
| 3 | Public route plus language=es, experiment=blue. |
CDN looks up catalog-home|es|blue. |
Matching cached page can be returned locally. |
| 4 | Cache miss for that key. | CDN calls origin with the selected public context. | Origin renders the es/blue page and response may be cached under that key. |
| 5 | A request for /basket with the same cookie. |
Function does not add an experiment variant or cache directive for the basket. | Private basket reaches its authoritative service. |
The important intermediate state is step 2. The function does not let arbitrary cookie text shape the cache. It reduces request data to a small set of allowed public values. If the user sends exp=anything-else, the edge must choose a safe default such as control, not create a new cache entry.
So far, the edge has removed a simple redirect from the origin path and made the public variation explicit. It has not personalized the catalog from a private profile, decided an inventory-sensitive offer, or made cached HTML safe by itself. The cache policy from the previous lesson still decides whether the selected representation is fresh and shareable.
What This Changes in the Request Path
Before this design, the origin receives every bare homepage visit just to choose a language and public experiment. The cache sees a less explicit response shape. After it, the edge turns a broad request into a stable public route and a bounded variant before cache lookup.
That changes the useful evidence too:
- Edge decision latency: p95/p99 execution time for redirect and variant selection. A slow function consumes the latency it was meant to save.
- Origin avoidance: requests served by redirect or edge cache versus requests still reaching origin.
- Variant distribution: counts for
control,blue, invalid bucket input, and cache key cardinality. A sudden rise in unique variants signals fragmentation. - Correctness: redirect loops, wrong-language reports, cache status by variant, and private-route cache bypasses.
- Policy convergence: which policy version made each decision. A partially deployed configuration can send identical requests down different paths.
Logs need enough context to answer “why did the edge choose this?” without recording sensitive cookies or tokens. A route, selected public language, experiment bucket, policy version, cache status, and request id are often more useful than a dump of headers.
Trade-offs and Limits
This design improves first-request latency and origin capacity for a cheap decision. It costs edge code, policy distribution, new observability, and a cache-variant contract that must stay aligned with the origin's rendering logic.
It can still fail when:
- replicated policy is stale or inconsistent across locations;
- a redirect rule creates a loop or chooses a route unsupported by the origin;
- an experiment bucket affects the body but is omitted from the cache key;
- an edge fallback makes a privacy-sensitive route appear public; or
- the function calls remote state on the hot path and gains no meaningful distance reduction.
An edge function does not solve database latency, transactional integrity, authorization design, or a cache purge after a content change. It may make those systems easier or harder to reach depending on its routing and cache choices.
The trade-off is situated. Use edge code for deterministic request shaping when its inputs are already present and the result has a bounded effect. Keep a decision at origin when it needs current private state, a durable write, or a complex workflow. The signal that the boundary is wrong is not merely “the function runs.” It is a combination of edge latency, origin dependency rate, cache-key cardinality, error rate, and user-visible correctness.
Check: The product team wants an edge function to show a customer's live loyalty discount on the public cached homepage. The discount requires a database lookup and changes frequently. Should the function add the discount value to the shared cache key?
Think first, then reveal.
Answer: No. The needed fact is private and frequently changing. Adding it to a shared key risks exposing personalized output and fragments the cache. Keep the authoritative discount decision in a private origin path, or redesign the product so only a safe, bounded public representation is handled at the edge.
Practice: Review an Edge Proposal
For each proposal, choose edge, origin, or needs a narrower contract, then justify it with the required data and the cache effect.
- Redirect
/to a supported language route fromAccept-Language. - Read the current account balance from the bank database before returning the homepage.
- Normalize
utm_*query parameters away before looking up a public campaign page. - Add the entire authentication token to every public page's cache key.
A good answer should mention:
- edge for the language redirect when the supported-language policy is replicated and fallback is defined;
- origin for the account balance because it is private, current, and authoritative;
- edge for bounded tracking-parameter normalization if it preserves the page's semantics; and
- a narrower contract for the token proposal: tokens are not a safe public cache-variant dimension, and the route may need private handling instead.
Connections
The previous lesson established that a CDN needs a correct key and a freshness policy. An edge function can shape both, so it must expose exactly which public dimensions it selects. The next lesson studies purging: once edge code creates variants, a purge must target the actual resulting key space rather than only the visible URL.
Resources
- [DOCS] Cloudflare Workers overview — Focus: Inspect request handlers, cache controls, bindings, limits, and observability as parts of an edge-runtime contract.
- [DOCS] Customize at the edge with CloudFront Functions — Focus: Compare lightweight viewer-event customization with a general backend workflow.
- [DOCS] Customize at the edge with Lambda@Edge — Focus: Identify the different events and trade-offs before treating any edge runtime as interchangeable.
Key Takeaways
- Edge functions are best for small decisions whose required inputs are already present at the edge and whose effects are bounded.
- The edge should turn raw request data into an explicit, safe public context; it should not blindly forward cookies or tokens into cache keys.
- A function that waits on authoritative private state often adds complexity without removing the meaningful latency path.
- Policy version, edge latency, origin dependency rate, variant cardinality, cache status, and correctness reports reveal whether the placement is working.
- Edge code shapes caching and routing, but origin remains responsible for durable state, private decisions, and complex workflows.
← Back to Caching, Workers, and Performance