Mobile loyalty apps (Starbucks, Chipotle, Dunkin) are unusually rich mobile system design topics. They combine payment processing, loyalty points, mobile ordering, geofencing, and the realities of physical retail integration. The Starbucks app in particular has been studied for its size and engagement — over 30M monthly active users.
Functional requirements
- Earn points (stars) for purchases — the earning rule engine should be server-side and configurable, so a purchase event comes in and the server applies current rules and writes the new balance. Expect follow-ups on how you claw back points when a purchase is later refunded.
- Pay with stored loyalty balance via QR/barcode — the QR encodes a short-lived token, not the balance itself. Be ready to explain why the client never holds the authoritative number and how you stop a screenshotted code from being reused.
- Mobile order ahead at a specific store — each store has its own menu, inventory, and prep queue, so orders are scoped to a store ID. A common probe: what happens when an item sells out between the client loading the menu and submitting the order.
- Customize drinks/items with options — this is where the data model gets tested. Options nest (a latte has size, milk, shots, syrups), each with its own price and availability, so a rigid column-per-option schema falls apart fast.
- Send/receive gift cards to friends — gift cards move stored value between accounts, so treat the transfer as a two-sided ledger entry with an idempotency key. Interviewers may ask how you prevent double-spending if the sender and recipient act at the same time.
- Find nearby stores with hours and inventory — a geospatial query (geohash or a spatial index) returns stores near the user’s coordinates, joined with per-store hours and live inventory. Cache slow-changing store metadata separately from fast-changing stock counts.
Architecture
Three modules: store / catalog, order, loyalty.
Loyalty mechanics
Each transaction adds points. Points have:
- Earning rules (purchase amount, item type, time of day) — model these as data, not code, so marketing can change “earn 2 stars per dollar” without a deploy. Rules key off purchase amount, item category, and time, evaluated server-side at transaction time.
- Tier system (free → reward levels) — tiers unlock rewards at thresholds (e.g., 150 stars for a free drink) and often decay over time. Be clear about whether tier status and redeemable balance are the same counter or two separate ones.
- Expiration (points expire after N months) — track earn dates per lot and expire oldest-first. A nightly batch job or lazy evaluation at read time both work; interviewers like hearing the trade-off between the two.
- Promotion events (double-points day, bonus stars) — these are time-boxed multipliers layered on the base rules. The gotcha is targeting: some promos apply to everyone, others to a specific user segment, so the rule engine needs a scope condition.
Server is authoritative — never let the client decide point balance.
Mobile payment
The Starbucks model: prepaid stored value. User loads $X via credit card; in-store, present QR code; system deducts from stored value.
Benefits to the company: float (held customer cash), reduced credit card fees per transaction, increased switching cost.
Implementation:
- User reloads stored value via credit card (real Stripe/Adyen call)
- Balance updates server-side
- Client shows balance
- In-store: app generates QR with token tied to the user account + brief expiry
- POS scans QR; server deducts
Mobile order ahead
User picks a store, customizes order, pays, app provides estimated pickup time.
Architecture:
- Client requests menu for the chosen store
- User customizes order
- Client submits order with idempotency key
- Server validates inventory and pricing
- Charges loyalty balance + reload if needed
- Server pushes order to in-store POS
- Server returns estimated ready time
Geofencing: when user is N miles from the store, app pushes notification. When they arrive, the order moves to the front of the queue.
Customization engine
Drinks have many options. Modeling:
- Base item (Latte) — the base carries a default price and default modifiers. Everything a customer changes is a delta against this base.
- Modifiers (size, milk, syrup, espresso shots) — store these as typed attributes with allowed values per item, not free text, so validation and pricing stay deterministic. Some modifiers are single-choice (size), others multi (extra shots), which the schema has to encode.
- Per-modifier price adjustments — each option carries its own price delta, and size often re-prices the whole drink. Compute the total server-side so the client can never submit a stale or tampered price.
- Calorie / nutrition impact — nutrition recalculates as modifiers change, so it’s a derived field the server owns. Some regions require showing it at point of sale, which makes correctness matter, not just display.
This is data modeling — custom orders need a flexible schema with strong validation.
Offline behavior
- Show last-known balance with “as of [time]”
- QR code generation works offline (cached token with longer expiry)
- Mobile order requires network (cannot place an order to a store without confirmation)
Push notifications
- Order ready — triggered by the kitchen marking the order complete, delivered fast because it’s time-sensitive. This is transactional, not marketing, so it bypasses any promotional throttle.
- Promotional offers — marketing-driven and the main source of opt-outs, so respect user preferences and quiet hours. These are the pushes you rate-limit.
- Nearby store reminders — fired by geofence entry, useful but easy to overdo. Cap frequency so a user who passes the same store daily isn’t pinged every time.
- Reward milestone reached — sent when a balance crosses a tier threshold, reinforcing the loyalty loop. Tie it to the same server event that updates the tier so the message and the state never disagree.
Push tokens stored per device. Throttle promotional pushes to avoid annoyance.
Frequently Asked Questions
How does the QR for in-store payment work?
Token-based. App generates a short-lived (5–10 minute) token tied to the user. Cashier scans QR; POS calls server to validate and deduct. Token cannot be replayed.
Why do loyalty apps push so many notifications?
Engagement metric. App teams are typically scored on DAU/MAU. Aggressive push tends to inflate metrics short-term but creates churn long-term. Balance is hard.
How is mobile order ahead synchronized with the in-store kitchen?
Orders push to a kitchen display system over a real-time channel. Status updates flow back as orders progress.
Keep sharpening your system design:
