We use analytics cookies.We use cookies to analyze site traffic and improve your experience.
Loading...
System Design Masterclass · Microservices Architecture
Free preview: the first 2 parts of this 9-part lesson.
Already bought the course? Sign in to read the whole lesson.
this lesson is part of
System Design Masterclass
Unlock this lesson and the 751 other paid lessons
$25 once, by PayPal
See the System Design courseread the rest of this lesson in
System Design Masterclass
Unlock this lesson and the 751 other paid lessons
$25 once, by PayPal
See the System Design coursein Microservices Architecture
This lesson is part of the full System Design Masterclass. Unlock it along with 769 other lessons for a one-time payment.
One-time payment by card or PayPal
Get Lifetime AccessOne-time payment: UPI, card or netbanking
Get Lifetime Access18 Foundation lessons are free, no payment needed. Try them now
It is easy and good
“It is really nice and good Please join the course”
At a large e-commerce company, three teams have a heated argument. The Sales team says a Customer has a name, email, lifetime spend, and preferred salesperson. The Shipping team says a Customer has a name, address, delivery preferences, and package history. The Billing team says a Customer has a payment method, billing address, tax ID, and invoice history.
They are all right. And they are all talking about different things.
In the real business, "Customer" has different attributes, different behaviors, and different rules depending on which part of the business is talking. The Sales team does not care about delivery preferences. The Shipping team does not care about lifetime spend. The Billing team does not care about preferred salesperson.
Building one universal Customer model that satisfies all three teams creates a monster: a 50-field object where most fields are irrelevant to any given use case, with conflicting validation rules and tangled business logic.
The Bounded Context pattern says: do not try to unify these models. Let each team have its own Customer model within its own boundary. Inside the Sales context, Customer means the sales version. Inside Shipping, it means the shipping version. At the boundary, they translate between models using well-defined interfaces.
Spotify discovered this the hard way. Their early architecture had a single User model shared across recommendations, playlist management, and payment processing. Changes to the User model for payments broke the recommendation engine. Bounded contexts solved it: each team got its own model of User with only the fields it needed.
A Bounded Context is a clear boundary within which a domain model is defined and consistent. The same term can mean different things in different contexts, and that is not a bug, it is a feature.
| Inside Sales Context | Inside Shipping Context | Inside Billing Context |
|---|---|---|
Customer { name, email, lifetimeSpend, salesRep } | Customer { name, address, deliveryPrefs } | Customer { paymentMethod, billingAddress, taxId } |
Order { items, discount, salesChannel } | Order { items, weight, shippingMethod } | Order { total, tax, invoiceNumber } |
Context boundaries define:
Customer means here)The boundary is explicit and enforced. Code inside the Sales context cannot import types from the Shipping context. Communication between contexts goes through defined interfaces: APIs, events, or translation layers.
In a TypeScript monorepo, this means separate packages with strict dependency rules. In , this means separate services with API contracts. The enforcement mechanism varies, but the principle is the same: no model leakage across boundaries.
If you want to watch a boundary like this enforced by a real database, the domain-driven design lesson builds Sales and Shipping as two PostgreSQL schemas, each with its own customer table, and shows the permission error when one context tries to read the other.