Discount Engine Low-Level Design: Rule Evaluation, Promotion Stacking, and Price Calculation

Promotion Schema

A discount engine evaluates active promotions against a cart and computes the final discounted price. The promotion schema captures what qualifies and what discount applies:

CREATE TABLE promotions (
  promo_id    UUID PRIMARY KEY,
  name        VARCHAR(128) NOT NULL,
  type        ENUM('cart_discount','item_discount','volume','bundle','loyalty') NOT NULL,
  conditions  JSONB NOT NULL,   -- {min_cart_value, eligible_skus[], user_segments[]}
  discount    JSONB NOT NULL,   -- {type: 'pct'|'fixed'|'free_item', value}
  priority    INTEGER NOT NULL DEFAULT 0,
  stackable   BOOLEAN NOT NULL DEFAULT FALSE,
  ab_variant  VARCHAR(32),      -- NULL = show to all
  start_date  TIMESTAMPTZ NOT NULL,
  end_date    TIMESTAMPTZ,
  created_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

Storing conditions and discount as JSONB allows adding new promotion types without schema migrations. Priority determines evaluation order and stacking resolution.

Rule Evaluation Engine

The evaluation engine operates on a cart context object containing: user_id, user_segments, cart_total, line_items (sku, quantity, price, category).

  1. Load all active promotions: WHERE start_date <= now() AND (end_date IS NULL OR end_date > now()). Cache this list with a 60-second TTL — promotions change infrequently.
  2. Filter by A/B variant: if ab_variant is set, only show this promotion to users assigned to that variant.
  3. Evaluate conditions for each promotion:
    • Cart total meets min_cart_value
    • At least one item's SKU is in eligible_skus (or list is empty = all SKUs)
    • User is in one of the user_segments (or list is empty = all users)
  4. Collect all matching promotions.

Stacking Policy

Three stacking strategies, selected at the engine configuration level:

  • Stack all: Apply every matching promotion. Each stackable promotion's discount adds to the total. Non-stackable promotions are skipped if a stackable one was already applied.
  • Highest priority only: Sort by priority descending, apply only the first matching promotion. Simplest to reason about; avoids runaway discounts.
  • Best deal: Compute the discount value each promotion would give independently, apply the one with the largest discount. Fair to the customer, predictable for the business.

In practice: non-stackable promotions compete with each other (best deal or priority wins); stackable promotions (e.g., a loyalty discount) always layer on top of whatever wins the non-stackable evaluation.

Volume and Bundle Discounts

Volume discounts are tiered by quantity of a specific SKU or category:

conditions: {eligible_skus: ["SKU123"], tiers: [
  {min_qty: 3, discount: {type: "pct", value: 10}},
  {min_qty: 5, discount: {type: "pct", value: 20}}
]}

Evaluation: find the highest tier the cart quantity satisfies, apply that discount. Only applies to the qualifying items, not the full cart.

Bundle discounts require multiple distinct products to be present:

conditions: {required_skus: ["SKU_A", "SKU_B"]}
discount: {type: "pct", value: 15, applies_to: "bundle_items"}

Evaluation: check all required SKUs are in the cart. Apply discount to those items only.

Price Calculation Order

Apply discounts in this sequence to reach the final cart total:

  1. Start with original prices for each line item.
  2. Apply item-level discounts (volume, bundle, item_discount promotions). Discount applies to qualifying items only.
  3. Sum discounted line item totals to get the discounted subtotal.
  4. Apply cart-level discounts (cart_discount promotions) to the discounted subtotal.
  5. Apply coupon code (if any) to the post-promotion subtotal.
  6. Add shipping and tax (calculated on post-discount subtotal).
  7. Apply loyalty or payment-method discounts (e.g., 2% off for paying with store credit).
  8. Return final total.

Return an itemized breakdown showing original price, each discount applied, and final price — both for displaying to the user and for audit/analytics.

Promotion A/B Testing

Assign users to variants deterministically using a hash of user_id and experiment_id:

variant = hash(user_id + experiment_id) % 100
# variant = 50: treatment

Deterministic assignment ensures the same user always sees the same variant across sessions and devices. Store the variant assignment in the cart context. The engine uses it to filter promotions with ab_variant set.

Measure conversion lift by comparing checkout rate and average order value between control and treatment groups. Run for at least 2 weeks before concluding results.

Real-Time Recalculation and Simulation

Recalculate the cart total on every modification (item added, quantity changed, coupon applied). The engine should complete in under 50ms for a typical cart. Optimizations: cache the active promotion list, short-circuit evaluation on first failing condition, avoid N+1 DB queries by loading all needed data upfront.

Display original and discounted prices side by side for each item showing the savings. Surface the promotion name so users understand why they got a discount.

Promotion simulation tool for marketing: given a proposed promotion definition, run it against a sample of recent carts to estimate: how many orders it would have applied to, total discount cost, average discount per order. This lets the business validate a promotion before activating it without impacting production traffic.

{
“@context”: “https://schema.org”,
“@type”: “FAQPage”,
“mainEntity”: [
{
“@type”: “Question”,
“name”: “How are promotion stacking rules evaluated?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Each promotion is tagged with a stackability group and an exclusion set; the engine applies promotions in priority order and, before applying each one, checks whether its exclusion set intersects with the already-applied set — rejecting it if so. This allows fine-grained rules like “loyalty discount stacks with sale prices but not with coupon codes” without hardcoding combinations.”
}
},
{
“@type”: “Question”,
“name”: “How does volume discount pricing work?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Volume tiers are stored as a sorted list of (min_quantity, unit_price) pairs; the engine finds the highest tier whose min_quantity does not exceed the cart line quantity using a binary search and applies that unit price to the entire quantity. Some implementations use a blended rate across tiers (tiered pricing) rather than a single tier price, which requires summing costs per tier band — the engine must clearly specify which model applies.”
}
},
{
“@type”: “Question”,
“name”: “How is the discount engine tested before a promotion goes live?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Promotions are deployed in a shadow or simulation mode where the engine evaluates the rule against a sample of real cart events from a replay queue and emits the would-be discounts to a monitoring topic without affecting actual orders. The output is compared against expected values from a QA fixture set and anomaly detectors alert if average discount depth or application rate falls outside configured bounds.”
}
},
{
“@type”: “Question”,
“name”: “How does the discount engine handle concurrent cart modifications?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “The cart is versioned with an optimistic lock token; the discount calculation is computed on a snapshot of the cart, and the write back includes a WHERE version=? condition so a concurrent modification causes a conflict that forces the client to re-fetch and recalculate. This prevents a race where two simultaneous adds each see a quantity below a volume threshold that would be crossed by their combined effect.”
}
}
]
}

See also: Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering

See also: Shopify Interview Guide

See also: Stripe Interview Guide 2026: Process, Bug Bash Round, and Payment Systems

Scroll to Top