What the low-level design round actually tests
It is not a pattern quiz. It is a maintenance test with a time limit.
What you will be able to do
- Explain what a machine-coding round scores beyond correctness
- Turn a requirement paragraph into entities, invariants and methods
- Spend the round's time in a defensible order
- Recognise pattern dumping as a failure mode, not a strength
The round is a maintenance test
The interviewer is not buying a design. They are buying the next six months of working in it. So the questions behind every observation are the same: if I asked you to add a new payment provider on Thursday, how much of this file would I have to read? If a stock reservation raced with another checkout, where would the bug live? If I gave this to a mid-level developer, could they change behaviour without changing structure?
That framing matters because it changes what you optimise for. A clever generic solution that needs a paragraph to explain scores lower than three boring classes with obvious names and a test each. Commerce systems are especially unforgiving here: money, stock and order state have invariants that no amount of pattern vocabulary can rescue once the model lets two contradictory states exist.
What is actually scored
- Requirements used, not listed. You asked about partial refunds, then modelled them. A requirements list that never appears in the design is a red flag.
- Entities with behaviour.
Order.cancel()that refuses to cancel a shipped order, rather than a service that checks three flags from outside. - Invariants made unrepresentable. No setter that allows a negative quantity; no public constructor for an order without a customer.
- Extensibility at the seams you named. If you claim new payment providers will be easy, there must be one interface with two implementations, not an if-chain.
- Working code and at least one test. Compiles, runs, demonstrates the happy path and one rejection.
- Names.
reserveStocksays more about a design than a class diagram does.
The five moves
How the ninety minutes usually go
| Slice | Minutes | Output |
|---|---|---|
| Clarify and scope | 0-8 | Three answered questions, a one-line scope, entities on the board |
| Model and invariants | 8-20 | Class list, relationships, six invariant sentences |
| Code the spine | 20-50 | Money, line items, cart, checkout service that runs |
| Second behaviour | 50-70 | Discount or second payment provider behind the same interface |
| Tests and walkthrough | 70-85 | Two passing tests, one failure path demonstrated |
| Extension conversation | 85-90 | Where observability, persistence and concurrency plug in |
What the spine looks like
This is deliberately unglamorous. Money is a value object so arithmetic cannot silently lose paise; a line computes its own total; the cart refuses duplicate SKUs; checkout is a service because it coordinates objects that should not know about each other.
record Money(long paise, Currency currency) {
Money plus(Money other) { requireSameCurrency(other); return new Money(paise + other.paise, currency); }
Money times(int qty) { return new Money(Math.multiplyExact(paise, qty), currency); }
}
final class LineItem {
private final Sku sku; // sku + variant, not a String
private final Money unitPrice; // locked when added
private int quantity; // only changes through methods
Money total() { return unitPrice.times(quantity); }
}
final class Cart {
private final Map<Sku, LineItem> lines = new LinkedHashMap<>();
void add(Sku sku, int qty, Money unitPrice) {
if (qty <= 0) throw new IllegalArgumentException("quantity must be positive");
lines.merge(sku, new LineItem(sku, unitPrice, qty),
(existing, added) -> existing.withQuantity(existing.quantity() + qty));
}
}double price and String sku on every field.Manager, Helper, Processor, Util.The sentence that closes the round
When time is called, do not apologise for what is missing. Summarise the design in three sentences: the invariants you enforced, the seam you left for extension, and the concurrency risk you would handle next. That summary is often the part the interviewer remembers, because it is the part that sounds like a colleague rather than a candidate.
Worth remembering
- The round measures whether your code can survive a second developer changing it, not whether you know the names of the design patterns.
- Entities and invariants come first. Classes follow from the verbs in the requirements, not from a catalogue.
- Sixty percent of the marks are in the first twenty minutes: what you clarify, what you name, and what you make impossible to represent.
- A small working system with three tests beats a large sketched one with none, every time.