SwadhyAI Notes

All Low-Level Design notes

Behavioral modeling

Sequence diagrams

A sequence diagram shows time: this message, then that one, then the return value. It is the cheapest way to make a use case visible when the class list alone is not enough.

Example: you have been talking for several minutes and the interviewer still cannot see park. An ASCII or whiteboard sequence — Controller → Lot → Strategy → Spot → Ticket — shows the order and who is not in the room.

Few columns

Five speakers. Cut the rest.

Time goes down

Order and return values, not boxes in a row.

One failure

Show where arrows stop.

Why a clock, not a class list sideways

Boxes in a row with no arrows and no time are not a sequence. Show which call happens first, what it returns, and where it stops on failure. Keep the cast small. Five is plenty. If you need twelve, some of those objects are not in this use case.

These are . Do not put network hops on an LLD sequence unless they asked for HLD. A cache is a class with get/put, not a regional Redis box.

Happy path — park

Driver to controller, controller to lot, lot to strategy, occupy, new ticket, save, ticket back to the driver. After you draw it, your code should match the arrows. If ParkingService starts calling pricing during park, either the diagram was a lie or the code wandered.

Happy path — park

Driver    Controller      Lot           Strategy      Spot     Tickets
  |            |           |               |           |          |
  |--park(car)->|           |               |           |          |
  |            |--allocate->|               |           |          |
  |            |           |--choose(free)->|           |          |
  |            |           |<---- spot -----|           |          |
  |            |           |-----------occupy---------->|          |
  |            |           |<---- ok -------------------|          |
  |            |           |-- new Ticket --            |          |
  |            |<--ticket--|               |           |          |
  |            |--------------------------------------save-------->|
  |<--Ticket---|           |               |           |          |

Failure — lot full

This is the that actually matters in this problem. Strategy returns empty. Occupy never runs. No ticket is saved. The driver gets an error. Draw the missing arrows on purpose — they are the design.

Failure — lot full

Driver    Controller      Lot           Strategy
  |            |           |               |
  |--park(car)->|           |               |
  |            |--allocate->|               |
  |            |           |--choose()---->|
  |            |           |<-- empty ------|
  |            |<-- LotFull-|               |
  |<- error ---|           |               |

No occupy. No ticket. Nothing saved.

Exit has different columns

Reusing the park diagram and scribbling “also pay” in the margin hides the new speakers. Pricing enters. Allocation leaves. Ticket moves ACTIVE → PAID → CLOSED. CLOSED → ACTIVE does not appear on this sketch because it is not a message anyone is allowed to send.

Happy path — exit

Driver    Controller     Tickets     Pricing      Ticket       Lot
  |            |            |           |           |           |
  |--exit(id)->|            |           |           |           |
  |            |----get---->|           |           |           |
  |            |<--ticket---|           |           |           |
  |            |--------fee(ticket)---->|           |           |
  |            |<------- money ---------|           |           |
  |            |----------------------pay---------->|           |
  |            |                       |      ACTIVE→PAID       |
  |            |------------------------------------release---->|
  |            |----------------------close-------->|           |
  |            |                       |       PAID→CLOSED      |
  |            |----save--------------->|           |           |
  |<--Receipt--|            |           |           |           |

Code that keeps the promise

The diagram is a promise. Park does not price. Full lot does not occupy. The Java below is the happy path and the empty-strategy stop, not a God service.

java
Ticket park(Vehicle vehicle) {
  Optional<Spot> chosen = allocation.choose(lot.freeSpots(), vehicle);
  if (chosen.isEmpty()) throw new LotFull();   // failure path: stop
  Spot spot = chosen.get();
  spot.occupy(vehicle);                        // never reached when empty
  Ticket ticket = Ticket.issue(spot, vehicle);
  ticket.activate();
  tickets.save(ticket);
  return ticket;
}

Receipt exit(TicketId id, Instant now) {
  Ticket ticket = tickets.get(id);
  ticket.pay(pricing.fee(ticket, now));        // ACTIVE → PAID
  lot.release(ticket.spotId());
  ticket.close();                              // PAID → CLOSED
  tickets.save(ticket);
  return new Receipt(id, ticket.fee());
}

// A retry that calls ticket.activate() on CLOSED throws.
// Do not draw that arrow. Do not write that assignment.

What to leave as a note, not a twelfth column

Two gates, one stall

Two park sequences can interleave on spot 101. That is a concurrency diagram. On this page, write one line: occupy must be atomic. Then point at race conditions and concurrent state transitions. Do not add Redis and a lock manager to the park sketch.

When they ask for the distributed version

Then the interview moved to system design. Gateways, queues, and stores belong on an HLD sequence. Until you make that clear, park is in-process. Mixing the two is how you run out of whiteboard and never finish occupy.

Where CLOSED → ACTIVE would sit — and why it does not

A webhook retry is not a reverse arrow on the exit sequence. If you need a picture, draw a short illegal fragment: Controller → Ticket.activate() ← rejected. Then stop. The machine lives on state machines.

Good signposting

“I will sketch park, then lot-full, then exit. Five columns. Pricing is not in park.”

Common miss

A row of boxes labeled Lot, Ticket, Redis, Kafka, CDN — no arrows, no time, no failure.

Common mistakes

A sequence that is only a class list sideways

Boxes in a row with no arrows and no time are not a sequence. Show which call happens first, what it returns, and where it stops on failure.

Putting network hops on an LLD sequence

Unless they asked for HLD, park is in-process messages. A cache is a class with get/put, not a regional Redis box.

How to draw it in five minutes

  1. Write the five column names. Cross out anyone who is not in this use case.
  2. Draw the happy arrows and the return values. Narrate them as you draw.
  3. Draw the failure where occupy never runs. Leave the empty space visible.
  4. Start a second sketch for exit. Do not reuse park columns if pricing just entered.
  5. Check the Java: every arrow is a call; every missing arrow is a missing call.

If the interviewer cannot see park after the sketch, the columns are wrong or time is not going down. Fix the picture before you open another file.

Return values are arrows too

Sketch the ticket coming back, the empty Optional, the LotFull. A sequence with only outbound calls hides the design: occupy never runs because choose returned empty. Draw the leftward arrows.

Read next

Takeaway

Draw park, then the failure where occupy never runs, then exit with different columns. ASCII is enough. Five speakers. Time goes down. The code must match the arrows — including the arrows you refused to draw.