Geo-Distributed A/B Testing with CDN Edge Workers

This article outlines how modern engineering teams configure CDN edge workers to conduct geo-distributed A/B testing at scale. By moving experimentation logic from the origin server or client-side JavaScript to edge compute nodes, teams eliminate the visual flicker typical of client-side tools and prevent the latency penalties of origin-based routing. The following sections detail the complete workflow, from extracting edge geolocation metadata and assigning deterministic variants to manipulating requests and streaming telemetry.

1. Intercepting Requests at the Edge

Edge workers (such as Cloudflare Workers, AWS CloudFront Functions, or Fastly Compute) execute serverless logic inside Points of Presence (PoPs) closest to the user. Teams configure these workers to intercept incoming GET requests before the CDN cache lookup or origin fetch occurs. This allows the edge worker to inspect headers, cookies, and network-level metadata to make routing decisions in single-digit milliseconds.

2. Reading Geolocation Metadata

CDNs automatically enrich incoming requests with geographic data derived from the client's IP address. Teams extract these properties directly from the runtime context or platform-specific headers:

  • Cloudflare: request.cf.country, request.cf.region, or request.cf.city
  • AWS CloudFront: Headers such as CloudFront-Viewer-Country, CloudFront-Viewer-Country-Region, and CloudFront-Viewer-Postal-Code
  • Fastly: Functions like client.geo.country_code and client.geo.city

By reading these values, teams establish audience targeting rules. For example, a test might run exclusively in the United Kingdom or split variants based on regional latency boundaries.

3. Implementing Variant Assignment and Persistence

To ensure a consistent user experience, edge workers must assign users to a variant (control vs. experiment) and persist that assignment across future visits.

  1. Cookie Inspection: The worker checks the Cookie header for an existing test identifier (e.g., ab_test_geo=B). If found, the user continues to receive that assigned variant.

  2. Deterministic Hashing: If no cookie exists, the worker generates an assignment. Rather than purely random selection, teams often hash a unique user ID (or a newly generated UUID) combined with the experiment name using an algorithm like MurmurHash or SHA-256:

    bucket = hash(userID + experimentID) % 100

    This guarantees uniform distribution according to the team's defined allocation weights (e.g., a 50/50 split).

  3. Setting Persistence: The worker appends a Set-Cookie header to the outgoing response, locking the client to that variant for the duration of the test.

4. Modifying Routing and HTML at the Edge

Once the variant is determined, teams serve the appropriate content using one of two primary patterns:

  • Subrequest Rewriting: The edge worker alters the upstream origin path or query parameter. For variant B, the worker fetches /experiments/v2/index.html from the origin while the user's browser URL remains /. This completely avoids external redirects (HTTP 301/302) and eliminates page flicker.
  • In-Flight HTML Rewriting: For localized content modifications (such as changing a headline, currency, or CTA button based on region), teams use an edge-native HTML parser (e.g., Cloudflare’s HTMLRewriter). The worker streams the original HTML from the origin, modifies specific DOM elements on the fly, and streams the modified response to the client with negligible overhead.

5. Logging and Analytics at the Edge

A/B testing requires strict tracking of impressions and conversions. Because the routing happens at the edge, client-side analytics might miss initial variant exposures or experience ad-blocker drop-offs.

Teams solve this by decoupling analytics logging from the response path:

  • Asynchronous Contexts: Workers use execution lifecycle hooks (such as event.waitUntil() or background tasks) to dispatch impression payloads to analytics endpoints, data warehouses, or edge key-value stores.
  • Log Streaming: Alternatively, workers annotate custom request headers (e.g., X-Experiment-Variant: B) that are captured by CDN real-time log streaming systems (like Datadog, BigQuery, or Amazon Kinesis), avoiding extra network calls during request execution.