This series follows a fictional conversation between an experienced engineer and his nephew. Every episode explores one stage of how software moves from an idea to production.
👦 Nephew: Uncle, requirements are clear. I checked the codebase — there's already a FavoritesService I can extend for Wishlist. Now can I open VS Code?
👨🦳 Uncle: Almost. Tell me — what do you think HLD even is? You've heard the term in every interview. What do you think it actually means?
👦 Nephew: Some kind of... diagram? Boxes connected with lines, before you start coding?
👨🦳 Uncle: That's what it looks like. That's not what it's for. Let me ask differently. Why do you think experienced engineers insist on drawing this before touching code, when they could just start building?
👦 Nephew: ...to plan the work?
👨🦳 Uncle: Closer, but still not it. Here's the real answer: HLD exists to decide, in advance, where the walls go — so that six months from now, when someone adds a new feature, they know exactly which room to build it in, without knocking down a wall that was holding up the ceiling.
👦 Nephew: That's a strange way to describe a diagram.
👨🦳 Uncle: Then let me show you, instead of describing it. That's the only way this actually lands.
What Talks to What
👨🦳 Uncle: Suppose we're building this at Flipkart. Not a college project — a company with hundreds of live services, where breaking one thing can affect ten others you've never even heard of. Here's the simplest picture for Wishlist.
Frontend
↓
Wishlist API
↓
Wishlist Service
↓
Database
👦 Nephew: That's it? Four boxes?
👨🦳 Uncle: That's it. HLD answers exactly one question, and nothing more — what talks to what. Not how the button looks. Not what fields the database table has. Just: which component calls which, and in what direction.
👦 Nephew: Then why does everyone treat it like it's such a big deal? This took ten seconds to draw.
👨🦳 Uncle: Because the value isn't in the ten seconds you spend drawing it today. The value is in what it protects you from later. Let me prove that to you.
The Test of a Good HLD
👨🦳 Uncle: Here's how you know if an HLD is actually good, not just simple. Ask this question: if the business asks for a new feature next quarter, does it fit into a new box — or does it force me to reopen and rewrite an existing one?
👦 Nephew: Give me an example.
👨🦳 Uncle: Suppose marketing comes back in three months and says: "When a wishlisted item's price drops, notify the user." Watch what happens to a badly designed system.
Frontend
↓
Wishlist API
↓
Wishlist Service ─────► (now also handles price-checking,
↓ also handles sending notifications,
Database also handles email formatting...)
👦 Nephew: Wishlist Service is doing four jobs now. That doesn't feel right.
👨🦳 Uncle: It isn't. And here's the real cost — to add that one feature, you had to open the existing Wishlist Service and change it. Every time you touch already-working code, you risk breaking something that was fine yesterday. That's the danger. Now watch what a properly bounded HLD looks like for the exact same new requirement.
Frontend
↓
Wishlist API
↓
Wishlist Service → Database
│
│ (event: "item_added")
▼
Notification Service
👦 Nephew: Oh — so Wishlist Service doesn't grow new responsibilities. It just... announces that something happened, and something else picks it up?
👨🦳 Uncle: Exactly. Wishlist Service's code didn't change at all to support this new feature. We added one new box, and one new arrow. That's the entire test of good HLD — can you add capability by adding a box, instead of editing one that already works?
Why This Matters More Than the Boxes Themselves
👦 Nephew: So the boxes aren't really the point. The boundaries are the point.
👨🦳 Uncle: Now you're seeing it. A box is just a name until you decide what it's allowed to know about, and what it's not. Wishlist Service should know how to save a wishlist item. It should not need to know how to format an email, or which notification provider the company uses this year. The moment a box starts knowing about things outside its job, every future change to that other thing risks breaking this box too.
👦 Nephew: So when I draw HLD, I'm not just drawing what exists today. I'm deciding what's allowed to change independently in the future.
👨🦳 Uncle: That's the whole craft in one sentence.
But Don't Over-Isolate Either
👦 Nephew: So should I add an event and a separate service for everything, just to be safe?
👨🦳 Uncle: No — and that's a real trap juniors fall into once they learn this lesson. Should Wishlist Service call Notification Service directly, or through an event, depends on things we haven't even talked about yet — how much traffic you expect, how much delay is acceptable, whether losing a notification occasionally is even a big deal. That's an entire lesson by itself, later in this series. For today, the only judgment you need is: notice when a box is being asked to do a job that isn't really its job, even if you don't solve the coupling perfectly yet.
Draw → Trace → Isolate
👦 Nephew: Give me something I can actually carry into every ticket, like Search-Understand-Extend from yesterday.
👨🦳 Uncle: Yes.
Draw
↓
Trace
↓
Isolate
Draw — sketch every box the new feature touches today. Frontend, API, service, database. Nothing fancy.
Trace — for each arrow, ask: what happens if the box on the other end is slow, or down, or returns an error? And separately — what's the next likely feature request here, six months from now?
Isolate — for anything that feels like it's forcing an existing, working box to grow a new responsibility, stop. Ask whether a new box and a thin connection would let the old one stay untouched.
Uncle's Line
"HLD isn't the blueprint. It's the decision about which walls can move later, and which ones you're building the whole house on top of."
👦 Nephew: So this whole exercise — it's not really about drawing boxes correctly today. It's about not having to rewrite them next quarter.
👨🦳 Uncle: Exactly. Redrawing an arrow on paper costs you a minute. Reopening a service that's been running fine in production for a year, just to bolt on one more responsibility, costs you regression risk, a longer review, and a much longer night if it goes wrong.
👦 Nephew: Okay. So now I know the pieces, what to reuse, and how they should connect — and where the walls should be able to move. Now, finally, code?
👨🦳 Uncle: Not yet, beta. You know where the rooms are, and which walls are load-bearing. You don't yet know what's inside each room — what functions Wishlist Service actually needs, what fields the database table really has, field by field. Today we decided where the walls go. Tomorrow, we walk inside and design the rooms.
🧠 Think Like an Engineer — Homework
Pick any app you use daily. Choose one small feature already inside it.
- Draw — sketch the boxes it likely touches: frontend, API, service, database. Four or five boxes at most.
- Trace — pick one arrow. What should happen if the box on the receiving end is slow or down? Separately, guess one realistic feature the product team might request for this six months from now.
- Isolate — using that guessed future feature, check your own diagram: would adding it force you to reopen an existing box, or would it fit as a new one? If it would force a rewrite, redraw the boundary so it wouldn't.
Don't worry about getting the "official" architecture right. The goal is to practice drawing boundaries that survive contact with the next feature request.
— End of Episode 3 —
Top comments (0)