Loyalty and Rewards System

Points Ledger, Tiers and Redemption

Design a loyalty platform where members earn points on purchases, redeem them for rewards and move between tiers, with a balance that is always correct, never spent twice and fully auditable.

Overview

A loyalty platform gives members points when they buy something and lets them spend those points on rewards. Behind the friendly app screen it behaves like a small bank: each member has a balance, every change to it must be recorded, and nobody may spend points they do not have.

The core idea is a ledger. Every change is a new row (earn 120, redeem 500, expire 40) and rows are never edited. The balance is the sum of the rows. A cached balance column makes reads fast, but it is updated in the same database transaction as the ledger row, so the two can never disagree.

Three things make the problem interesting. Retries are everywhere: a store's point-of-sale terminal, a queue consumer and a partner's webhook will all send the same event twice sooner or later, and each must count once. Redemptions race: a member tapping redeem on two phones must not spend the same points twice. And points age: each batch expires 12 months after it was earned, so the system must know which points are left in which batch.

Questions to ask first

  • How many members and events? — 50 million members, 5 million earn events and 500,000 redemptions a day
  • Which channels earn points? — Stores, web, app and partner brands; all send an order or transaction ID
  • Must earning be instant? — Visible within seconds; checkout does not wait for it
  • Must redemption be instant? — Yes, the member is waiting; 300 ms at p99 is our target
  • How do points expire? — Each batch 12 months after it was earned; oldest points are spent first
  • How do tiers work? — Qualifying points in a calendar year; upgrade at once, downgrade only at year end
  • What about returns? — A refund takes back the points that order earned

What you will be able to do

  • Explain why a ledger of immutable entries beats a single mutable balance, and keep a cached balance consistent with it.
  • Make earn and redeem idempotent with unique reference IDs, and stop double spending with a conditional debit.
  • Track points in lots so that spending takes the oldest points first and expiry removes only what is left.
  • Design tier qualification, promotions and partner earning, including reconciliation and returns.

Key concepts

  • Append-only ledger
  • Idempotency keys
  • Conditional debit
  • Row-level locks
  • Point lots and FIFO
  • Rolling expiry
  • Tier qualification
  • Earn rules
  • Partner reconciliation
  • Points liability

Functional requirements

  • Earn points on purchases from stores, web, app and partners, once per order even when the event is sent twice
  • Redeem points for rewards; a redemption either debits the full cost or fails with no change
  • Expire each batch of points 12 months after it was earned, spending the oldest points first
  • Keep a tier per member from qualifying points in the calendar year; upgrade at once, review downgrades at year end
  • Apply promotion rules (bonus multipliers, category bonuses, tier bonuses) chosen by marketing without a deploy
  • Take back points when an order is refunded
  • Show balance, points expiring soon, tier progress and a paginated history

Non-functional requirements

  • Correctness first: the balance always equals the sum of ledger entries and never goes below zero from a redemption
  • Every write is idempotent on a reference ID (order, redemption or partner transaction)
  • Redemption answers in 300 ms at p99 (a target we chose); earned points show within a few seconds
  • Ledger entries are never updated or deleted; corrections are new entries
  • Checkout keeps working if the loyalty platform is down; earn events wait in the queue

Interview questions

  • Why use a ledger instead of a balance column?
  • How do you stop the same purchase earning points twice?
  • Two redemptions arrive at the same moment. What happens?
  • How do you expire points 12 months after they were earned?
  • How do tier upgrades and downgrades work?
  • How do you handle a double-points day for all members?
  • How do partner integrations stay correct?
  • What does finance need from this system?

Sign up free to read the full topic

More System Design topics

Start free on Cariara · Coding problems · System design studio