Sitemap

Progressive Feature Rollouts in VCL: Safely Enabling Features for 5% of Traffic

3 min readMar 27, 2026

--

When working with Fastly and VCL, one of the most powerful patterns you can implement is progressive delivery at the edge.

Instead of deploying a feature and exposing it to all users at once, you can gradually roll it out to a percentage of traffic, observe behavior, and increase confidence before going fully live.

This post focuses purely on the VCL mechanics behind that approach.

A Minimal 5% Rollout Pattern in VCL

Here’s a clean example of enabling a new flow for a subset of requests:

if (
req.http.X-Env == "prod"
&& randombool(5, 100)
&& req.url.path ~ "^/api/v2/resource/([^/]*)$"
) {
set req.http.X-Resource-ID = re.group.1;
set req.http.X-Feature-Flag = "v2_enabled";
error 680;
}
if (req.http.X-Service == "EDGE_RENDER") {
call feature_recv;
}

Breaking Down the Pattern

This is a three-layer gate that determines whether a request should enter a new execution path.

1. Environment Guard

req.http.X-Env == "prod"

The first condition ensures the logic only applies in a specific environment.

This is useful when:

  • You share VCL across staging and production
  • You want explicit control over where rollouts happen

2. Percentage-Based Traffic Sampling

randombool(5, 100)

This is the core rollout mechanism.

  • Returns true ~5% of the time
  • Evaluated per request
  • Stateless and fast

This effectively creates a 5% traffic slice at the edge.

3. Route Targeting with Regex

req.url.path ~ "^/api/v2/resource/([^/]*)$"

Instead of applying globally, we scope the rollout to a specific route.

The regex also captures a dynamic segment:

  • re.group.1 → resource identifier

This allows you to extract values directly from the URL.

4. Passing State via Headers

set req.http.X-Resource-ID = re.group.1;
set req.http.X-Feature-Flag = "v2_enabled";

Headers act as a lightweight communication channel between layers.

They allow downstream logic to:

  • Know which feature path was selected
  • Access extracted parameters
  • Log or debug rollout behavior

5. Switching Execution Paths with Custom Errors

error 680;

This is a key VCL pattern.

Get John Sourgiadakis’s stories in your inbox

Join Medium for free to get updates from this writer.

Instead of mutating the request inline, you:

  • Raise a synthetic error
  • Handle it in vcl_error

Example:

if (obj.status == 680) {
set obj.status = 307;
set obj.http.Location = "/api/v2/alternate";
return (deliver);
}

This keeps your logic:

  • Modular
  • Easier to reason about
  • Cleaner to extend

6. Delegating to Subroutines

if (req.http.X-Service == "EDGE_RENDER") {
call feature_recv;
}

Once flagged, the request can be processed by a dedicated subroutine.

This enables:

  • Separation of concerns
  • Reusable logic blocks
  • Cleaner VCL organization

Making the Rollout Incremental

The beauty of this pattern is how easy it is to scale:

randombool(10, 100)   # 10%
randombool(25, 100) # 25%
randombool(50, 100) # 50%
randombool(100, 100) # 100%

You move gradually from:

  • limited exposure
  • to partial rollout
  • to full adoption

Improving Consistency (Advanced)

One limitation of randombool() is that it operates per request, not per user.

If you need consistency, you can base the decision on a stable identifier:

if (digest.hash_md5(req.http.User-ID) % 100 < 5) {

This ensures:

  • The same user always gets the same experience
  • True feature flag behavior

Why This Works Well in VCL

This pattern is effective because:

  • Decisions are made at the edge, before origin load
  • No backend deployment is required to adjust rollout
  • It composes well with existing routing logic
  • It is extremely fast and stateless

Final Thoughts

VCL gives you low-level control over request flow, and with just a few primitives — conditionals, regex, headers, and randombool() — you can build a robust progressive delivery system.

Start small, observe behavior, and increase gradually.

That’s the essence of safe rollouts at the edge.

--

--

John Sourgiadakis
John Sourgiadakis

Written by John Sourgiadakis

Entrepreneur wannabe & SRE and Devops