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 part of this 7-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”
Two teams build : Order Service and Inventory Service. They share a database because "it is simpler." Order Service writes to the orders table. Inventory Service writes to the inventory table. Everyone is happy.
Then Order Service needs to join orders with inventory to show stock status on the order page. The developer writes a join query. Works perfectly. Then Inventory Service refactors its inventory table, renames a column, changes a data type. Order Service breaks. Nobody told them. The deployment rolls back, angry Slack messages fly, and a postmortem is scheduled.

The join did not disappear when the tables moved into separate services. It turned into calls, and now you pay for each one.
The top lane is the version everyone writes first. Fetch the orders, loop over them, fetch each customer. It is the natural shape of the code and it is two thousand round trips.
The bottom lane is the same answer in one call. Collect the ids, ask once, join in memory. On loopback that is 131 milliseconds against 0.5, and loopback is the friendliest network this call will ever meet.
Now read the table, because distance is what decides. One call costs one round trip no matter how far away the service sits: 39 milliseconds to Mumbai, 337 to Sao Paulo. Two thousand calls cost two thousand round trips: 77 seconds and 674 seconds. The fan does not get a little worse with distance. It gets multiplied by it.
Which gives you the real design rule behind database-per-service. The pattern is sound. The price is that every read spanning two services has to be designed as one batched call, a materialised view, or an event that keeps a local copy fresh. If your boundaries force a per-row lookup across the network, the boundary is in the wrong place.
This is the shared database trap. The moment two services read from the same table, they are coupled through the database schema. You cannot change one service's data structure without risking the other. You cannot deploy independently. You cannot use different database technologies. You have built a distributed monolith with extra network .
The Database per Service pattern breaks this coupling: each service owns its database, and no other service is allowed to access it directly. Period.
Amazon learned this in the early 2000s when they decomposed their . The mandate from Jeff Bezos was clear: no service can directly access another service's data store. All communication goes through well-defined APIs. This mandate forced clean separation and enabled Amazon to scale to the infrastructure company it is today.