← Envoy Interview Insights

Envoy·Software Engineer·Onsite - System Design / Architecture·Intermediate

IntermediatePrefer not to say
Jul 2026

Summary

System design round at Envoy for a software engineer role. The prompt was an OO shopping cart design, which sounds straightforward until you actually have to think through immutability, coupon extensibility, and tax modeling at the same time.

Questions Asked (1)

Q1

Design an object-oriented shopping cart module for an e-commerce system. The cart should support adding items, updating quantities, applying coupons (multiple types like percentage off and buy-one-get-one), computing tax by state, and locking the cart after checkout so it can no longer be modified.

System DesignTechnical Trade-offsData Modeling
Author's notes

I spent the first few minutes asking clarifying questions which I think was the right call.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and constraints, then design a class hierarchy that separates concerns: Cart, CartItem, Coupon (with subclasses), TaxCalculator, and CheckoutService. Focus on extensibility for new coupon types and tax rules, and enforce immutability after checkout via a state pattern or lock flag.

Pro tip: Discuss trade-offs between using inheritance vs. composition for coupons and tax strategies, and mention how you would handle concurrency and persistence to show production readiness.

1. Clarify Requirements and Scope

Ask questions to understand expected scale, concurrency needs, and whether coupons can stack or have exclusions. Confirm that tax is based on shipping address and that locking is permanent.

2. Identify Core Entities and Relationships

Define classes like Cart, CartItem, Coupon (abstract), PercentageCoupon, BOGOCoupon, TaxCalculator, and CheckoutService. Establish associations: Cart has many CartItems, Cart has applied Coupons, Cart uses TaxCalculator.

3. Design Coupon and Tax Strategies

Use the Strategy pattern for coupons and tax calculation to allow easy addition of new types. For coupons, consider a common interface with methods like apply(Cart) and isApplicable(Cart).

4. Implement Cart State and Locking

Use a State pattern (e.g., ActiveState, LockedState) or a simple boolean flag with guard clauses to prevent modifications after checkout. Ensure all mutating methods check the state.

5. Address Edge Cases and Trade-offs

Discuss concurrency (e.g., optimistic locking), persistence, and how to handle coupon conflicts. Mention trade-offs between simplicity and extensibility.

Key Points to Mention

  • Use of design patterns: Strategy for coupons and tax, State for cart lifecycle.
  • Separation of concerns: Cart manages items, Coupon handles discounts, TaxCalculator computes tax.
  • Extensibility: Adding new coupon types or tax rules without modifying existing code (Open/Closed Principle).
  • Immutability after checkout: Enforce via state pattern or lock flag, and consider making Cart immutable after checkout.
  • Concurrency: How to handle simultaneous updates (e.g., optimistic locking, versioning).
  • Persistence: How cart state is stored and retrieved, and how locking interacts with persistence.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.