42. Low-Level Design (LLD)
Answer as submitted
“Yes — LLD is where I spend a large part of my design effort, because it decides whether an implementation is clean and maintainable.”
Expanded answer
Yes, and LLD is where the maintainability of a system is actually decided, long before architecture diagrams are drawn. Class and component design: one responsibility per class, stated in a sentence a reviewer can disagree with, dependencies pointing inward through ports the calling layer owns, names taken from the ubiquitous language rather than from the ORM, and design patterns applied where they resolve a named force — a strategy because the rule varies, a decorator because the behaviour is cross-cutting — instead of because a catalogue exists. When a responsibility needs the word “and” to describe it, that is the design pointing out which two classes it wants to become. Behavioural design: a sequence diagram for the main flow and one for each way it can fail, a lifecycle expressed as an explicit state machine with the legal transitions named, the transaction boundary drawn on the diagram rather than discovered in the code, and the concurrency and idempotency rules stated in terms of what the database enforces. The error paths are the whole point, because that is where the ambiguity lives and where the implementer would otherwise have to guess. Data design: tables with the constraints that enforce the invariants, keys chosen for stability, the indexes derived from the queries the feature will actually run, a forward-only migration that applies while the previous version is still serving traffic, and an explicit mapping that keeps the persistence model, the domain object and the wire DTO from being conflated. Contract design: every endpoint designed before it is written, including which status code each failure returns, which validation rules belong at the edge and which in the domain, and how pagination behaves on the first and last page — plus versioned event schemas and the failure mode and timeout of every external integration. Deliverables and review: a design document a reviewer can disagree with, pseudocode for the algorithms that are hard to get right, testability notes written before the tests exist, and a design review before coding — after which the design evolves where the code does, in pull requests, rather than stopping at the first commit.
| Part of the LLD | The deliverable | The ambiguity it removes |
|---|---|---|
| Class and component design | a responsibility sentence per class, ports, dependency direction | who owns the rule, and which way the dependencies point |
| Behavioural design | a sequence per flow including each error path, a state machine, the transaction boundary | what happens when it fails, and where the transaction opens and commits |
| Data design | constraints, keys, the indexes with their queries, the migration plan, the three mappings | whether an invariant lives in the schema or in code, and how the change ships without downtime |
| Contract design | every endpoint with all of its statuses, versioned event schemas, external integrations with failure modes | what the implementer does for each rejection, and what happens when a dependency is unavailable |
| Deliverables and review | the design document, pseudocode for the hard parts, testability notes, the review before coding | whether the design is agreed before it is expensive to change |
| Open questions | each with an owner and a date | decisions being made by whoever types first |
Live low-level design workflow proof
The running component below changes its part-of-the-design/result view through real event binding. Select a part to see the deliverable, the reasoning behind it, and the evidence that the detail is actually there.
Choose a part of the low-level design
Select a part to inspect the deliverable, the reasoning and the evidence.
$ one responsibility per class · ports and dependency direction · ubiquitous-language naming · patterns applied where they resolve a named force
Each class gets a responsibility that can be stated in a sentence a reviewer is able to disagree with, and the dependencies point inward through ports the calling layer owns. Patterns are applied where they resolve a named force — a strategy because the rule varies, a decorator because the behaviour is cross-cutting — rather than because a catalogue exists. When a responsibility needs the word "and" to describe it, that is the design pointing out which two classes it wants to become.
classes whose responsibility needs an "and" to state: 0 ports owned by the calling layer: all patterns applied without a named force: 0 names taken from the ubiquitous language rather than from the ORM: all ports a unit test needs to stand in for: 3, with no database involved
What good LLD buys
Source files
Select a file to inspect the proof with syntax highlighting and line numbers. The first file is the code running the component above; the others are the design document itself with its error paths and open questions, the lifecycle as an executable state machine, and the pseudocode for the allocation algorithm with its invariants stated first.
Acceptance criteria
- Covers all five parts of the low-level design the answer describes.
- Draws a sequence for each error path and states the transaction boundary explicitly.
- Shows an interactive proof of choosing a part and reading the evidence.
- Assigns each invariant to the layer that can enforce it, and names the query behind every index.
- Reviews the design before coding and carries open questions with an owner and a date.