One Edge to Rule the Traffic Paths

Shopify’s traffic engineering team had a problem that will sound familiar to anyone who has watched infrastructure accreted over years: there wasn’t one way for traffic to reach the platform, there were at least six. Distinct paths existed for general-population Shopify Core traffic, GenPop apps and services (with or without an edge provider in front), PII-restricted Core traffic that had to stay in a specific geographic region, PII-restricted apps and services, and publicly accessible APIs requiring mutual TLS (mTLS) authentication.

Every new feature had to be built multiple times or selectively applied to some paths and not others. Debugging was slow because observability was fragmented across all those routes, and onboarding engineers meant teaching them to tell six different ingress patterns apart. The team decided the only sane move was to consolidate: build one network edge and one routing layer behind it. Two projects emerged — Möbius, the unified edge itself, and Shopify Front End (SFE), the routing tier that receives traffic from Möbius and dispatches it onward.

What “The Edge” Actually Means Here

The classic definition of a network edge is the point where an enterprise-owned network connects to a third-party one. Cloud complicates that definition slightly, since Shopify rents servers and networks from providers, and even uses a third-party provider to front its network. Still, the line holds: as long as those resources are used and controlled by Shopify, they count as Shopify’s network. So the edge, for Shopify, is the point where requests from outside that network arrive.

About a year before Möbius launched, a small number of applications were already being handled through an edge, but automating that approach at scale wasn’t practical. Möbius and SFE were designed together, which gave the team a clean separation between the edge layer and the routing layer from the start.

The Routing Layer: SFE

SFE is a unified routing layer deployed in many regions. Routing clusters behind it can receive any kind of web traffic from Möbius — Core or applications alike. The clusters are nginx deployments with custom Lua routing logic that considers criteria like the client’s IP address and the domain used to reach Shopify. For PII-restricted workloads, parallel deployments of the same cluster code run in the relevant regions.

Applications and services are handled via a centralized API that receives requests from Kubernetes controllers in every cluster running those apps. That API links the domain names an application declares to the clusters where it is actually deployed, and it enables both active/active load balancing (two instances serving requests simultaneously) and active/passive (only one instance serving at a time).

Putting load balancing at the routing layer instead of in DNS gives near-instantaneous traffic shifts rather than waiting on TTLs. It also keeps those decisions off the client side, giving Shopify direct command and control over where traffic goes.

The Edge Layer: Möbius

Möbius’s job is deliberately narrow: take traffic from outside Shopify and get it inside, stably, securely, and performantly. “Outside” means any client connecting from beyond a Shopify cluster; “inside” means, as far as Möbius is concerned, the routing cluster with the lowest latency to the receiving edge point-of-presence (PoP).

Möbius handles TLS and TCP termination with clients, doing that termination as close to the client as possible. That improves request speed and DDoS protection, and lets the team filter malicious requests before they ever reach Shopify’s clusters. This was already the case for GenPop Core traffic, but Möbius standardizes it across everything. Certificate handling for shop domains was already in place; Möbius adds an automated path for application domains too.

The team deliberately avoided rebuilding domain logic for the edge. SFE already tracks which domains applications respond to, so Möbius piggybacks on the SFE controller’s work. Handlers in the centralized API configure domains at the edge via API requests to the vendor, signal that traffic is expected on those domains, and forward requests to SFE. The API handler also manages DNS challenges to prove domain ownership before traffic starts flowing, and obtains valid certificates.

Before Möbius, an application owner wanting edge benefits had to configure their domain manually: validate ownership, get a certificate, set up routing. Now that setup is fully automated — the owner just configures ingress and DNS. The final step is intentionally manual: a DNS change pointing the application’s domain from a direct-to-cluster record to Möbius. Keeping that step manual means application owners own the migration and can verify nothing breaks.

Observability was added to support that confidence. Application owners get easy access to edge logs for their app, a view of which domains will be configured at the edge, and status information for each domain. If a domain isn’t configured or behaving correctly, the owner can spot it immediately.

Beyond Unification

With the edge unified, work can proceed on features that would have been impractical to roll out across six parallel paths. Teams are already improving edge caching and exploring other edge capabilities Shopify doesn’t use yet. There are also projects to handle cluster-to-cluster communication without sending traffic out through the edge and back — something SFE makes possible.

There is one deliberate exception to onboarding everything onto Möbius and SFE: applications that Möbius or SFE themselves depend on to function. Putting those behind the edge would create a crash-loop dependency, where the edge needs the app to work and the app needs the edge to work.

The practical win is in the explanations. Describing how traffic reaches Shopify no longer requires enumerating six paths and their conditionals. Fewer whiteboards are needed to onboard new engineers — though, as the team notes, future edge capabilities may consume those whiteboards again.