---
title: "How Shopify Dynamically Routes Storefront Traffic"
description: "Shopify’s Storefront Renderer team rewrote the storefront implementation beginning in 2019 and needed a way to shift traffic between the legacy and new versions while migrating features. Using nginx with OpenResty, Lua modules, a control plane, and the spy chatbot, they moved routing rules from a Lua file into JSON payloads that could be created, updated, enabled, disabled, and deleted without a CI or deployment cycle. Rules selected shops and request subsets through filters, then controlled rendering and verification rates, including forward verification, reverse verification, and self-verification in the nearest region. During nginx request processing, matching occurs in the rewrite phase; verification is scheduled with timers in the log phase so duplicate requests run asynchronously after the client response path. The system supported gradual rollouts, parity checks, and resilience testing under Redis failures, while the team planned to simplify routing after the new storefront served almost all traffic."
---

# How Shopify Dynamically Routes Storefront Traffic

[Shopify](https://yomu.fyi/company/shopify) · 2023-10-18 · Apr 9, 2021

**Type:** Explainer

## Summary

Shopify’s Storefront Renderer team rewrote the storefront implementation beginning in 2019 and needed a way to shift traffic between the legacy and new versions while migrating features. Using nginx with OpenResty, Lua modules, a control plane, and the spy chatbot, they moved routing rules from a Lua file into JSON payloads that could be created, updated, enabled, disabled, and deleted without a CI or deployment cycle. Rules selected shops and request subsets through filters, then controlled rendering and verification rates, including forward verification, reverse verification, and self-verification in the nearest region. During nginx request processing, matching occurs in the rewrite phase; verification is scheduled with timers in the log phase so duplicate requests run asynchronously after the client response path. The system supported gradual rollouts, parity checks, and resilience testing under Redis failures, while the team planned to simplify routing after the new storefront served almost all traffic.

## Context

The 2019 storefront rewrite aimed to make the storefront faster, but the team needed to continually shift requests between the legacy and new implementations as features migrated. It also needed to verify parity, test regional behavior, and investigate dependency failures without disrupting client traffic.

## Approach / What changed

The team used nginx with OpenResty and Lua modules to match dynamic routing rules stored as JSON in a control plane. The spy chatbot managed those rules, while filters, shop targeting, render and verification rates, and nginx timers supported gradual rollouts, asynchronous forward or reverse verification, self-verification, and resilience testing.

## Takeaways

- Rules can target all shops or selected shop IDs and partition requests with comma-separated filters; changing the filter list still requires a full deployment.
- render\_rate and verify\_rate support gradual rollout and sampling, while reverse\_verify\_rate checks new-storefront responses against the legacy implementation asynchronously.
- The verifier uses nginx timers to duplicate requests after the original request cycle, allowing dependency-failure tests, including Redis outages, without making clients wait for both upstreams.

**Tags:** [Architecture](https://yomu.fyi/topic/architecture), [Lua](https://yomu.fyi/topic/lua), [Migrations](https://yomu.fyi/topic/migration), [nginx](https://yomu.fyi/topic/nginx), [Testing](https://yomu.fyi/topic/testing)

- Source: [Shopify](https://shopify.engineering/dynamically-route-storefront-traffic)
- Source URL: https://shopify.engineering/dynamically-route-storefront-traffic
- Ingested by Yomu: 2026-08-31T01:09:52.050Z

[Read original post](https://shopify.engineering/dynamically-route-storefront-traffic)
