0
0
LLDsystem_design~7 mins

Pricing strategy (discounts, coupons) in LLD - System Design Guide

Choose your learning style9 modes available
Problem Statement
Without a clear pricing strategy, applying discounts and coupons can lead to inconsistent pricing, revenue loss, and customer confusion. Naive implementations often mix pricing logic with business logic, making it hard to update or extend discount rules without risking bugs or errors.
Solution
A well-designed pricing strategy separates discount and coupon logic into modular components that calculate final prices based on defined rules. This approach allows flexible, reusable, and testable discount policies that can be combined or extended without affecting core business logic.
Architecture
Order Item
Discount Rule
Coupon Rule
Final Price

This diagram shows how order items are processed through discount and coupon rules, which the price engine uses to calculate the final price.

Trade-offs
✓ Pros
Enables flexible addition and combination of multiple discount and coupon rules.
Separates pricing logic from business logic, improving maintainability and testability.
Supports complex pricing strategies like stacking discounts or conditional coupons.
✗ Cons
Adds complexity to the codebase compared to hardcoded discounts.
Requires careful design to avoid conflicts or unintended discount stacking.
Performance overhead if many rules are evaluated for each pricing calculation.
Use when your system needs to support multiple, changing discount and coupon rules, especially if discounts depend on conditions like user type, order size, or time.
Avoid if your pricing is simple and static, such as a fixed discount applied uniformly without conditions, or if discount logic rarely changes.
Real World Examples
Amazon
Amazon uses modular pricing strategies to apply various discounts and coupons dynamically based on user segments, promotions, and product categories.
Shopify
Shopify's platform allows merchants to define complex discount rules and coupon codes that combine multiple conditions and actions.
Uber
Uber applies promotional coupons and discounts through a flexible pricing engine that considers user history, location, and time.
Code Example
The before code mixes discount logic directly in the order class, making it hard to extend. The after code separates discount and coupon rules into classes, and a price engine applies them in sequence. This modular design allows easy addition of new discount types without changing core order logic.
LLD
### Before: naive discount logic mixed in order processing
class Order:
    def __init__(self, items):
        self.items = items

    def calculate_total(self):
        total = sum(item.price for item in self.items)
        # Apply 10% discount if total > 100
        if total > 100:
            total *= 0.9
        return total


### After: modular pricing strategy with discount and coupon rules
from abc import ABC, abstractmethod

class DiscountRule(ABC):
    @abstractmethod
    def apply(self, price, order):
        pass

class TenPercentOver100(DiscountRule):
    def apply(self, price, order):
        total = sum(item.price for item in order.items)
        if total > 100:
            return price * 0.9
        return price

class CouponRule(ABC):
    @abstractmethod
    def apply(self, price):
        pass

class FixedCoupon(CouponRule):
    def __init__(self, amount):
        self.amount = amount

    def apply(self, price):
        return max(price - self.amount, 0)

class PriceEngine:
    def __init__(self, discount_rules, coupon_rules):
        self.discount_rules = discount_rules
        self.coupon_rules = coupon_rules

    def calculate_final_price(self, order):
        price = sum(item.price for item in order.items)
        for rule in self.discount_rules:
            price = rule.apply(price, order)
        for coupon in self.coupon_rules:
            price = coupon.apply(price)
        return price

# Usage example
class Item:
    def __init__(self, price):
        self.price = price

order = Order([Item(60), Item(50)])
discounts = [TenPercentOver100()]
coupons = [FixedCoupon(5)]
engine = PriceEngine(discounts, coupons)
final_price = engine.calculate_final_price(order)
print(final_price)  # Outputs discounted and coupon-applied price
OutputSuccess
Alternatives
Hardcoded Discounts
Discount logic is embedded directly in business code without abstraction.
Use when: Choose when discount rules are very simple, rarely change, and system complexity must be minimal.
Rule Engine
Uses an external or dedicated rule engine to evaluate discount conditions and actions.
Use when: Choose when discount logic is very complex, requires non-developers to update rules, or must integrate with other business rules.
Summary
A modular pricing strategy separates discount and coupon logic from core business code.
This design enables flexible, maintainable, and testable pricing rules that can combine multiple conditions.
It prevents revenue loss and confusion caused by inconsistent or hardcoded discount implementations.