LLD Interview Framework (45-60 minute round)
Overview
- Time budget (60 min; compress proportionally for 45)
- Step 1: Clarify requirements (never skip)
- Step 2: Identify entities (nouns) and behaviors (verbs)
- Step 3: Relationships
- Step 4: Class diagram (ASCII/UML cheat-sheet)
- Step 5: Pick patterns (justify with the problem)
- Step 6: Define APIs before bodies
- Step 7: Code
- Step 8: Extensibility (say it, show 1 example)
- Step 9: Concurrency (almost always asked in fintech)
- Step 10: Testing and edge cases
- What interviewers evaluate
- Common mistakes
- How to talk while coding
- Scoring rubric (typical 1-4 per dimension; hire usually needs ~3 average with no 1s)
- One-page checklist (memorize)
Part of the Interview Prep series. Dotted-underline words are glossary terms: hover for the meaning or open the Glossary. Track your progress on the Interview Prep tracker. Series index: Start here.
Goal: show structured thinking, clean OO modeling, working code, and awareness of extensibility/concurrency. Interviewers rarely want a perfect system; they want a runnable core with sound design and clear trade-offs.
Time budget (60 min; compress proportionally for 45)
| Min | Phase | Output |
|---|---|---|
| 0-5 | 1. Clarify requirements | Written list of functional + non-functional + out-of-scope |
| 5-10 | 2. Entities, behaviors, relationships | Nouns/verbs table, rough class diagram |
| 10-15 | 3. Patterns, APIs, package layout | Interfaces and public method signatures |
| 15-45 | 4. Code core flow | Compiling classes, in-memory storage, a main/demo |
| 45-52 | 5. Extensibility + concurrency | Verbal walk-through, small code changes |
| 52-60 | 6. Testing, edge cases, Q&A | Test cases listed, complexity discussed |
Step 1: Clarify requirements (never skip)
Ask, then write them down in the doc/editor and confirm.
- Actors: who uses it (customer, admin, merchant, system)?
- Core use cases (top 3-5): e.g. ATM: insert card, auth PIN, withdraw, check balance, deposit.
- Scope: what is out (UI, real DB, real network, auth)? "Single JVM, in-memory" is the usual answer.
- Rules/constraints: pricing, limits, capacity, expiry, priority, max retries.
- Non-functional: concurrency expected? latency? scale? consistency? extensibility axes ("new payment method next quarter?").
- Failure behavior: insufficient funds, timeouts, duplicate request?
- Money questions (fintech): currency? precision (
BigDecimal/paiselong)? refunds? idempotency? audit trail?
Template to say aloud: "I'll assume X, Y. Out of scope: Z. I'll design for extension on A and B. Sound good?"
Step 2: Identify entities (nouns) and behaviors (verbs)
Underline nouns in the requirements -> candidate classes; verbs -> methods; adjectives/enums -> attributes/types.
Example (wallet): "Users have wallets, add money from bank, pay merchants, and view transactions."
| Noun | Becomes | Verb | Owner |
|---|---|---|---|
| User | entity | addMoney | Wallet |
| Wallet | entity (holds balance) | pay | WalletService (coordinates 2 wallets) |
| Transaction | entity/value, immutable | view history | TransactionRepository |
| Money | value object |
Heuristics: entity has identity & lifecycle (Account); value object is immutable and compared by value (Money); service is stateless coordination (TransferService); enum for closed sets (TxnStatus); interface where behavior varies. Put behavior on the object that owns the data (Tell, Don't Ask); use a service only when logic spans multiple entities.
Step 3: Relationships
- Association (uses), Aggregation (has-a, independent lifetime), Composition (owns, dies together), Inheritance (is-a), Realization (implements).
- Decide cardinality (1..*), ownership, and which side holds the reference.
- Prefer composition + interfaces; inheritance only for true is-a.
Step 4: Class diagram (ASCII/UML cheat-sheet)
+------------------+ +----------------------+
| <<interface>> | | Wallet |
| PaymentMethod | |----------------------|
|------------------| 1 * | - id: String |
| + pay(Money) |<>------| - balance: Money |
+------------------+ | + debit(Money) |
^ ^ | + credit(Money) |
| | +----------------------+
UpiMethod CardMethod | 1
| has
v *
+--------------+
| Transaction |
+--------------+
Legend: -|> extends ..|> implements <>-- composition/aggregation --> association
Visibility: + public - private # protected
Draw only: classes, key fields, public methods, relationships. Takes <5 minutes. Then show the main flow as a sequence in one line: Client -> WalletService.transfer -> lock(from,to) -> from.debit -> to.credit -> repo.save(txn).
Step 5: Pick patterns (justify with the problem)
| Signal in requirements | Pattern |
|---|---|
| "different pricing/algorithms/payment types" | Strategy |
| "object behaves differently by status" | State |
| "create X depending on type/config" | Factory |
| "notify multiple parties when Y happens" | Observer |
| "undo/redo, queue operations" | Command |
| "validate through several steps" | Chain of Responsibility |
| "add features in combinations" | Decorator |
| "single shared instance" | Singleton (state why; mention DI alternative) |
| "wrap third-party API" | Adapter |
| "simple entry point over many services" | Facade |
| Do not stack patterns for show. Two well-justified beats six decorative. |
Step 6: Define APIs before bodies
Write the public interface (method names, parameters, return, exceptions). Example:
interface WalletService {
Wallet createWallet(String userId);
void addMoney(String walletId, Money amt, String idempotencyKey);
Transaction transfer(String from, String to, Money amt, String idempotencyKey) throws InsufficientFundsException;
List<Transaction> history(String walletId, int limit);
}
Guidelines: return domain objects/Optional, not null; typed exceptions for business failures; immutability for results; idempotency key on mutations (fintech); no UI/IO inside the domain.
Step 7: Code
Order: enums/value objects -> entities -> interfaces -> core implementation -> repository (in-memory) -> service/facade -> Main demo.
- Code the happy path end-to-end first, then edge cases. A working vertical slice beats many half classes.
- Package-private/
private finalby default; constructor injection; nostaticmutable state. - Collections:
Mapfor lookup by id,Dequefor history/LRU,PriorityQueuefor scheduling,EnumMapfor transitions. - Meaningful names; small methods; no commented-out code; consistent exceptions.
- Skip boilerplate verbally ("getters omitted") to save time; ask if allowed.
- Finish with a runnable
mainshowing 2-3 scenarios + a failure case.
Step 8: Extensibility (say it, show 1 example)
"To add a new payment method: implement PaymentMethod, register in factory. No change in CheckoutService (OCP)." Prepare answers for: new type, new rule, new notification channel, new pricing, persistence swap (Repository), multi-currency, pluggable policy at runtime.
Step 9: Concurrency (almost always asked in fintech)
Identify shared mutable state and invariants, then pick granularity:
- What's shared? (balance, seats, inventory, counters, cache)
- What invariant? (no negative balance, no double booking, total conserved)
- Choose: per-entity lock (
ReentrantLock) with lock ordering for multi-entity,ConcurrentHashMapatomic ops, atomics/CAS for counters, optimistic versioning for low contention,BlockingQueuefor async work. - Idempotency for duplicate requests; atomicity of compound operations (check-then-act).
- Mention: deadlock, visibility (
volatile), immutability, lock scope minimal, never call external code under a lock. See00-concurrency-for-lld.md.
Step 10: Testing and edge cases
- Unit: each class with fakes (DI makes this easy); table of inputs/expected.
- Edge: null/empty, zero/negative amount, boundary limits, duplicates, insufficient funds, expired items, capacity full, same-account transfer, rollbacks on partial failure.
- Concurrency: N threads x M ops, assert invariants; stress with latches.
- State machines: every illegal transition rejected.
- State complexity (time/space) of the core operations (e.g. LRU get/put O(1)).
What interviewers evaluate
- Requirement handling: asks the right questions, states assumptions.
- Object modeling: sensible entities, responsibilities, relationships; not one God class.
- Principles/patterns: SOLID applied, patterns justified.
- Code quality: compiles, readable, naming, error handling, immutability, Java idioms.
- Extensibility: new requirement handled with minimal change.
- Concurrency & correctness: race conditions, atomicity, money correctness.
- Testability and edge cases.
- Communication: structured, collaborative, accepts hints, explains trade-offs.
- Time management: working solution within time.
Common mistakes
- Jumping straight to code without clarifying; designing for imaginary requirements (over-engineering).
- One giant class; or 30 classes with nothing running.
if/elseon type everywhere; public mutable fields;staticglobals.doublefor money; ignoring currency/rounding.- Ignoring concurrency or locking the whole world with one
synchronized. - Naming a pattern but implementing something else; forcing Singleton everywhere.
- Silent failures (returning
false/nullfor everything); swallowing exceptions. - Mixing I/O (printing) into domain logic; no demo/test.
- Not handling "what if two requests arrive together?" in a payment system.
- Defensive silence when stuck: instead think aloud and propose a simpler version.
How to talk while coding
- Narrate intent, not syntax: "I'm making
Moneyimmutable so I can share it across threads safely." - State trade-offs: "HashMap now; I'd swap to a DB behind this
Repository." - Flag shortcuts: "I'm skipping getters/validation here; in production I'd add X."
- Check in: after requirements, after the diagram, after the API ("OK to proceed?").
- When a hint is given, take it graciously and adjust; do not argue.
- Say what you'll do next, then do it. Leave 1-2 min to summarize design + known gaps.
- If blanking: write the interface first; state the invariants; implement the simplest correct version.
Scoring rubric (typical 1-4 per dimension; hire usually needs ~3 average with no 1s)
| Dimension | 1 (No) | 2 (Weak) | 3 (Good) | 4 (Strong) |
|---|---|---|---|---|
| Requirements | none asked | few, not recorded | clear scope & assumptions | probes edge cases, NFRs, money rules |
| Modeling | God class | some classes, blurred roles | clean entities/services | right abstractions, value objects, invariants |
| Patterns/SOLID | none / misused | named, loosely applied | fits problem, justified | minimal and elegant, knows alternatives |
| Code | doesn't compile | partial, messy | working core, readable | idiomatic, tested flow, error handling |
| Extensibility | rewrite needed | with big edits | small localized edits | seams already in design |
| Concurrency | not considered | mentions synchronized | correct locks/atomics | ordering, granularity, idempotency, trade-offs |
| Communication | silent | one-way | structured | collaborative, drives discussion |
One-page checklist (memorize)
Clarify -> Entities -> Relations -> Diagram -> Patterns -> APIs -> Code (happy path first) -> Edge cases -> Extensibility -> Concurrency -> Tests -> Summary