Building a coupon and promotions engine is one of those deceptively complex challenges that separates scalable e-commerce platforms from those that struggle with edge cases. When customers expect to stack discounts, apply BOGO deals alongside free shipping, and see accurate pricing before checkout, your system needs more than just a simple discount calculator. Today, we're exploring the architecture behind a flexible promotions engine that handles multiple deal types while maintaining consistency, fairness, and performance.
Architecture Overview
A modern promotions engine sits at the intersection of several critical concerns: catalog knowledge, cart state, business rules, and real-time evaluation. The architecture typically consists of four main layers working in concert. First, a Promotion Service manages the lifecycle of all active deals, storing metadata like discount type (percentage, fixed amount, BOGO, bundle, free shipping), eligibility rules, and stacking constraints. This service connects to a Rules Engine that evaluates whether a promotion applies to a specific cart based on conditions like minimum purchase amount, product category, customer segment, or temporal constraints.
The second critical layer is the Evaluation Engine, which processes all applicable promotions and determines the final discount. This component handles the heavy lifting of stacking logic, ensuring promotions are applied in the correct order and respecting any exclusivity rules set by the business. Finally, the Cart Service integrates these pieces together, triggering promotion evaluation whenever cart contents change and maintaining the line item breakdown so customers understand exactly what discounts they're receiving. This separation of concerns allows each component to scale independently and makes testing promotion logic straightforward.
One key design decision worth highlighting is caching. Promotions don't change on every request, so storing active deals in memory with a short TTL dramatically reduces database queries during peak traffic. However, you'll need an event-driven invalidation mechanism to ensure stale promotions don't linger in cache after they expire.
Why This Architecture Matters
E-commerce companies often underestimate promotions complexity until they launch a Black Friday campaign and their checkout system buckles under unexpected edge cases. By separating concerns and building an explicit Rules Engine, you gain flexibility to launch new promotion types without redesigning the entire system. The evaluation layer acts as your safety net, preventing conflicts and ensuring consistent results regardless of the order in which customers add items to their cart.
Design Insight: Handling Promotion Stacking
So, how do you actually evaluate promotion stacking when multiple coupons apply to the same cart? The answer lies in establishing clear stacking rules and evaluating promotions in a deterministic order. Most platforms implement one of three strategies: exclusive stacking (only the best discount applies), sequential stacking (discounts apply in priority order), or combinatorial stacking (certain promotions can combine while others cannot).
The key is making this decision explicit in your data model. Each promotion should declare its stacking behavior, and your Evaluation Engine should sort applicable promotions by priority before calculating results. For instance, a free shipping promotion might always apply alongside a percentage discount, but two percentage discounts might be mutually exclusive. Some teams implement a "promo group" concept where promotions belong to categories that don't stack with each other. The critical part is that this logic lives in one place, your Evaluation Engine, so business teams, marketing, and engineering all reference the same truth about how deals combine.
Watch the Full Design Process
Watching an architecture diagram come together in real time reveals the iterative thinking behind these decisions. You'll see how initial simplicity gradually becomes sophistication as we layer in complexity, business requirements, and edge cases. Check out the full design session on your preferred platform:
Try It Yourself
The beauty of system design is that principles apply across industries and use cases. Whether you're building a promotions engine, payment processor, or inventory system, the fundamental approach stays the same: break the problem into focused components, make your constraints explicit, and test edge cases ruthlessly.
Head over to InfraSketch and describe your system in plain English. In seconds, you'll have a professional architecture diagram, complete with a design document.
Top comments (0)