Loading…
How Shopify Reduced Storefront Response Times with a Rewrite
2023-10-18
- Source
- Shopify
- Published
- Added to Yomu
Summary
Shopify rewrote the server-side Storefront Renderer, which loads Liquid themes and storefront data before returning HTML, because the legacy Rails-monolith implementation had developed stricter performance demands and rising time-to-first-byte as traffic grew. The new single-purpose application separates storefront traffic from checkout, admin, and API traffic, uses active-active replication with dedicated read replicas, and adds mechanisms for high-load resilience. During migration, a Ruby verifier compares status codes, headers, and bodies from both implementations, while a custom Lua module on OpenResty samples production traffic and routes requests based on verification results. The rollout had reached more than 90% feature parity, and the new implementation averaged 4x faster server response times, with ongoing work aimed at full parity and retiring the legacy system.
Context
The previous storefront implementation lived in Shopify’s Rails monolith, whose storefront requests became progressively slower as platform traffic increased. Rising server time-to-first-byte affected merchant storefront performance, while storefront traffic had stricter performance and high-load requirements than other monolith components.
Approach / What changed
Shopify built a dedicated storefront application with active-active replication and dedicated read replicas, then separated storefront routing from the Rails monolith. A Ruby verifier compared legacy and new responses in production, while a custom Lua module on OpenResty sampled traffic and routed requests based on verification results. Autoscaling, in-memory caching, circuit breakers, fallback behavior, and Toxiproxy testing supported resilience.
Takeaways
- The verifier compared response status codes, headers, and bodies between the legacy and new implementations, using production traffic to identify parity differences without adding latency to buyer responses.
- The new implementation uses active-active replication and reads from dedicated replicas, while autoscaling and in-memory caching help it handle flash-sale traffic and reduce pressure on external data stores.
- At the reported stage, the rewrite had exceeded 90% feature parity and averaged 4x faster server response times; the stated goal was 100% parity before retiring the legacy implementation.