# Price Engine Low-Level Design: Rule Evaluation, Currency Conversion, and Real-Time Price Updates

Source: https://www.techinterview.org/post/3233470062/lld-price-engine/
Updated: 2026-04-18 · techinterview.org

## Price Engine Low-Level Design

A price engine computes the effective selling price for a product at request time by evaluating a prioritized set of rules: base price, customer tier discounts, volume breaks, promotional overrides, and multi-currency conversion. Interviewers focus on rule evaluation order, cache invalidation, and consistency under concurrent rule updates.

## Requirements

### Functional

  - Compute the effective price for a (product, variant, customer, quantity, currency) tuple.

  - Support rule types: base price, customer tier (bronze/silver/gold), volume break, flash sale override, and cost-plus markup.

  - Apply multi-currency conversion using configurable exchange rates refreshed from an external feed.

  - Allow merchants to schedule rules with start and end timestamps.

  - Provide a price explanation response listing which rules fired and their contributions.

### Non-Functional

  - Price computation under 20 ms for a single (variant, customer) pair at the 99th percentile.

  - Rule updates propagate to all nodes within 30 seconds.

  - Consistent pricing: two requests for the same tuple within the same second must return the same price.

## Data Model

  - **price_rule**: id (UUID), rule_type (BASE | TIER | VOLUME | SALE | COST_PLUS), priority (lower number wins), scope_type (PRODUCT | VARIANT | CATEGORY | ALL), scope_id, customer_segment_id (nullable), min_quantity (default 1), amount_type (FIXED | PERCENT), amount, currency, starts_at, ends_at, active.

  - **exchange_rate**: id, from_currency, to_currency, rate, source, fetched_at — latest rate per pair is the active one.

  - **customer_tier**: customer_id, tier (BRONZE | SILVER | GOLD), effective_from.

  - **price_cache**: key (VARCHAR, composite of variant_id + segment_id + currency), price_cents, rule_snapshot_version, computed_at, expires_at.

## Core Algorithms and Flows

### Priority-Ordered Rule Evaluation

At compute time the engine fetches all active rules matching the request context, ordered by priority ascending. Rules are filtered by: scope (variant ID, product ID, category path, or ALL), customer segment, quantity threshold, and active time window (starts_at and ends_at bracket the current timestamp). The evaluation loop applies each rule in priority order. FIXED rules set the price absolutely and halt further evaluation; PERCENT rules stack multiplicatively. The final result is the price after all applicable rules have been applied, along with a list of rule IDs and their contributions for the explanation response.

### Multi-Currency Conversion

Rules are stored in the merchant base currency. After rule evaluation the engine looks up the latest exchange_rate for the requested currency pair and multiplies the computed base-currency price. Rates are refreshed from an external feed (e.g., ECB or Open Exchange Rates) every 15 minutes by a background job and written to the exchange_rate table. A materialized view maintains the latest rate per pair, eliminating a subquery at compute time.

### Customer Tier Pricing

The customer_tier table is resolved at request time using the customer_id from the auth token. The tier is translated to a customer_segment_id that maps to TIER-type price rules. If no tier record exists the customer is treated as the default segment. Tier lookups are cached in Redis per customer_id with a 5-minute TTL, reducing database load for high-traffic authenticated sessions.

### Cache Invalidation

The price cache key encodes variant_id, customer segment_id, and currency. A rule_snapshot_version counter is incremented on any price_rule write. Cached entries include the version at compute time; on cache hit the engine compares the stored version against the current global version (held in Redis as a single key). A version mismatch triggers a synchronous recompute and cache refresh. This approach avoids per-key invalidation fan-out when a broadly scoped rule (e.g., a sitewide sale) changes.

## API Design

  - `GET /v1/prices?variant_id={id}&quantity={n}&currency={c}` — returns effective price for anonymous buyer.

  - `GET /v1/prices?variant_id={id}&customer_id={cid}&quantity={n}&currency={c}` — returns effective price for authenticated buyer with tier applied.

  - `GET /v1/prices/{variant_id}/explain?customer_id={cid}&currency={c}` — returns price breakdown listing all rules evaluated.

  - `POST /v1/price-rules` — creates a new pricing rule with scope, priority, and schedule.

  - `PATCH /v1/price-rules/{id}` — updates rule parameters; increments rule_snapshot_version.

  - `DELETE /v1/price-rules/{id}` — deactivates a rule; increments rule_snapshot_version.

  - `POST /v1/prices/bulk` — batch price lookup for up to 500 variant/customer pairs; used by cart rendering.

## Scalability Considerations

  - The rule set for any given request context is small (typically under 20 rules); evaluation is CPU-bound and completes in microseconds, making the 20 ms budget dominated by network and cache latency rather than computation.

  - Rules are loaded into an in-process LRU cache on each engine node; the global version key in Redis provides a lightweight invalidation signal without requiring a pub/sub fan-out per node.

  - Bulk price endpoints for cart rendering are essential: fetching 500 prices individually at 20 ms each would take 10 seconds; bulk evaluation amortizes rule loading and exchange rate lookup across all variants in a single call.

  - Exchange rate fetches are isolated from the price compute path; stale rates (up to 15 minutes old) are acceptable and the background refresh job retries on failure without blocking price serving.

  - Flash sale rules with narrow time windows are pre-loaded by a scheduler 60 seconds before their starts_at time, preventing a thundering herd of cache misses at sale launch.

See also: [Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering](https://www.techinterview.org/post/3233460275/scale-ai-interview-guide-2026-data-infrastructure-rlhf-pipelines-and-ml-engineering/)

See also: [Shopify Interview Guide](https://www.techinterview.org/post/3233459924/shopify-interview/)

See also: [Stripe Interview Guide 2026: Process, Bug Bash Round, and Payment Systems](https://www.techinterview.org/post/3233460268/stripe-interview-guide-2026-process-bug-bash-round-and-payment-systems/)
