A/B testing on AWS CloudFront with Lambda@Edge

AWS Lambda@Edge and CloudFront CDN

The Use Case

A/B testing example (by Maxime Lorant from Wikipedia)

Server-side vs Client-side A/B testing

The Scenario

  • Front-end A/B testing: static content, SPA or any cacheable content in general.
  • Content is served through CloudFront CDN and we don’t want to lose benefits of the CDN: caching and geographical proximity.
  • We cannot (or do not want to) pollute our front-end with any switching logic. So the logic must be on the CDN not to lose it.
    Lambda@Edge is the way of putting logic on the CDN.
  • For simplicity, I’m serving content from S3 buckets directly. But the idea may be extended to any http/https source.
  • We have two complete versions of front-end: Main and Experiment. They are served from two separate S3 buckets (separate CloudFront Distribution Origins).
  • We want to randomly switch a fraction of users to Experiment.
  • We want a user to stay on the same version for the duration of the session (the browser “session”, remember we don’t have any login).

How it works

Stable A/B testing with Lambda@Edge
  1. The browser request is directed to the closest AWS Edge Location. The request may contain the X-Source cookie.
  2. The Viewer Request Lambda@Edge function gets triggered on every request. If the cookie is not in the request, it rolls dice to decide which version to send the user to and adds the cookie accordingly.
  3. The Distribution decides whether the request is a cache hit. We are forwarding the X-Source cookie and the cookie is part of the cache key (see CloudFront settings, below).
  4. If the request is a cache-miss, it triggers the Origin Request function. This function is triggered only on cache-miss and introduces no overhead on hits. By default, the Distribution forwards cache-misses to the Main Origin. If the cookie points to Experiment, the request Origin is modified.
  5. The content is served by either S3 bucket. S3 completely ignores the cookie.
  6. The response from the Origin triggers the Origin Request function. This happens only on cache misses. It adds a Set-Cookie header to set X-Source. Remember the cookie might have been added by the Viewer Request function and not by the browser.
  7. The decorated response, including the Set-Cookie header, is cached by the Distribution. The cache key is the object URI and the X-Cookie.
  8. The response is returned to the browser from the Edge location.
  9. The browser complies with the Set-Cookie headers, setting the cookie. The version will be stable for the duration of the session.
  10. In case of a cache hit, the response would have been returned immediately from the Edge Location and it would include the Set-Cookie header also cached (7).

Benefits of this approach

CloudFront Distribution settings

CloudFront Distribution, Origins
CloudFront Distribution, Default Behaviour settings

Lambda functions

Viewer Request

Origin Request

Origin Response

Function Execution Role

Attaching Lambda@Edge to CloudFront Distribution


Gotcha! (by Bill Larkins, from Wikipedia)

N.Virginia AWS Region only

No environment for Lamba@Edge

Execution logs roam across CloudWatch Regions

Change Host header when changing Origin

Switching Origin in Origin Request only

Forwarded Cookies are part of the cache key

Cache invalidation drops all versions of an object

Deleting functions used as Lambda@Edge





Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Getting started with ROS Lunar on Arch Linux

“The cucumber is bitter? Then throw it out. There are brambles in the path? Then go around them.”

A person holding a phone with the Android 11 easter egg of turning a volume knob up to 11.

I need a cloud database: Firebase or CloudKit?

Building a server monitoring system using ESP8266 and integrating it to Home Assistant

Azure Key Vault with Java, Spring Boot and Jasypt

Project Week — TechCrunch Top 10

Integrating and Configuring Hadoop Cluster and Start services using Ansible Playbook

Getting Started with .NET Development on Linux with .NET Core 2.1 — Part 2

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Lorenzo Nicora

Lorenzo Nicora

More from Medium

Streaming data from DynamoDB to your Data Lake (Part- I)

Migrating Transactional Data to MongoDB in AWS with the Zaloni Arena Data Governance Platform

Amazon Kinesis Data Streams

Creating producer and consumer using AWS Lambda for AWS MSK Cluster