Siddhant Deval
Siddhant Deval
system design15 min read

Pragmatic UML & Visual Architecture as Code

Academic UML is bureaucratic overhead, but lean class diagrams and asynchronous sequence lifelines written in Mermaid.js are the most efficient way to communicate low-level design in teams and interview loops. This article teaches the 20% of UML notation that delivers 80% of clarity, plus a 30-minute LLD sketching framework for interview time pressure.

Series·Part 5 of 13

TypeScript Low-Level Design & Object-Oriented Architecture

Pragmatic UML & Visual Architecture as Code

In TypeScript 5+, OOP is an architectural contract, not an inheritance tree: enforce domain invariants at compile time, encapsulate mutation strictly within aggregates, and invert dependencies so high-level business policy never couples to execution details. But a contract no one can read is not a contract — it is a private note. The ability to communicate that architecture visually, precisely, and quickly is what separates engineers who design well from engineers who design well and lead effectively.

Academic UML is a bureaucratic discipline invented for software tools of the 1990s. The full UML 2.5 specification spans 796 pages of notation that no practitioner uses in day-to-day engineering. What teams and LLD interviewers actually need is a ten-notation subset that can be written in a text editor, rendered by any modern markdown renderer, and committed alongside the code that implements it. Mermaid.js is that tool — and this article teaches the 20% of it that delivers 80% of architectural clarity.


1. The Anti-Pattern Graveyard: The Sprawling PNG Screenshot Diagram

Here is the workflow that every engineering team has experienced at least once:

Timeline of a static PNG diagram:

Day 1  → Architecture meeting. Senior engineer opens draw.io, creates a 
          colorful flowchart with 40 boxes, curved arrows, and drop shadows.
          PNG exported and pasted into Confluence.

Day 3  → PR introduces a new PaymentStrategyRegistry — not reflected in the diagram.
          No one updates the PNG. No one knows who owns the draw.io file.

Day 12 → New team member reads the diagram and implements against it.
          Discovers three components it shows do not actually exist.
          Spends two hours debugging before finding the correct code path.

Day 30 → The diagram is archived because it is "too far out of date to be useful."

Outcome: 0 hours of documentation value returned on N hours of drawing investment.

The core failure is that the diagram lives outside the repository. It cannot be reviewed in a PR diff. It cannot be automatically rendered. No one knows it is wrong until someone acts on it.

The fix is diagrams-as-code: Mermaid.js blocks embedded directly in Markdown files, committed to the repository, and rendered automatically by GitHub, GitLab, and every major documentation platform.


2. Class Diagram Syntax: The Practical Subset

2.1 Visibility Modifiers and Members

Mermaid's class diagram syntax maps directly to TypeScript's access model:

Mermaid Prefix TypeScript Equivalent Visual in Diagram
+ public Plus sign before member
- private Minus sign
# protected Hash
~ Package / internal (no TS equivalent) Tilde
$ static Underlined member name
* Abstract method Italicized

2.2 Relationship Arrows: The Five That Matter

Mermaid uses specific arrow heads to encode the five relationship types from classical UML. These are the five your team and interviewers use — nothing else is required:

Relationship Mermaid Syntax Meaning
Inheritance A <|-- B B extends A
Implementation A <|.. B B implements A (dashed)
Association A --> B A holds a reference to B
Aggregation A o-- B A aggregates B (hollow diamond)
Composition A *-- B A owns B (solid diamond)

2.3 Stereotype Annotations

Add <<interface>>, <<abstract>>, <<aggregate>> labels to clarify architectural intent:


3. Sequence Diagram Syntax: Modeling Async Lifelines

Class diagrams model structure. Sequence diagrams model behavior over time. In the fintech domain, every payment flow involves multiple actors, async boundaries, and failure branches — sequence diagrams are how you communicate these precisely.

3.1 Basic Sequence Diagram Anatomy

Notation Meaning
->> Synchronous call (solid arrow)
-->> Response / return (dashed arrow)
actor External user or system
participant Internal component
autonumber Auto-number each step

3.2 Failure Branches with alt

The alt block is Mermaid's conditional branch — analogous to an if/else. This is the most important block for modeling payment flows where success and failure paths diverge:


4. The Fintech Domain: A Complete Mermaid Sketch

Here is the full class diagram for the Enterprise Fintech Ledger & Order Fulfillment domain as it exists after Parts 1–4. This is the reference diagram for the rest of the series:

A Mermaid class diagram rendered as a technical architecture overview of the fintech domain. Dark background. Shows IPaymentGateway interface with StripeGateway and AdyenGateway implementations via dashed arrows. OrderAggregate with solid diamond to LineItem (composition). LineItem with solid diamond to Money (value object). IOrderRepository interface with dotted arrow from OrderAggregate labeled 'persisted via'. All stereotypes labeled with double angle brackets.
A Mermaid class diagram rendered as a technical architecture overview of the fintech domain. Dark background. Shows IPaymentGateway interface with StripeGate…

5. The 30-Minute LLD Interview Sketching Framework

In a 60-minute LLD interview, the first 30 minutes are almost always more important than the second 30. The candidate who produces a clear class diagram and sequence diagram in the first 20 minutes controls the interview — they are setting the scope, naming the entities, and demonstrating architectural thinking before writing a single line of code.

5.1 Step-by-Step: 0–20 Minutes

Minutes 0–5: Clarify Requirements

Candidate asks:
1. "What are the primary entities? (Order, Payment, Account?)"
2. "What are the core operations? (Create, Confirm, Cancel, Refund?)"
3. "What consistency guarantees do we need? (Strong consistency for payments?)"
4. "What is the expected scale? (Concurrent users?)"

Output: A plain English contract statement:
"Design a Payment & Order system that allows a customer to:
 - Create an order with multiple line items
 - Confirm and pay for the order
 - Receive a refund if payment fails
 Consistency: strong (no double-spend). Scale: 1,000 concurrent users."

Minutes 5–15: Sketch the Class Diagram

Start with entities (nouns from the requirements):
  Order, LineItem, Customer, Payment, Ledger

Add key attributes (3–4 per entity):
  Order: orderId, status, totalAmount
  Payment: paymentId, orderId, amount, status

Add relationships (ask: who owns whom?):
  Order *-- LineItem (composition — lineitems die with order)
  Order --> Payment (association — payment exists independently)

Add interfaces (what does the system need to replace?):
  IPaymentGateway — Stripe, PayPal, Adyen all implement this
  IOrderRepository — Postgres, MongoDB, InMemory all implement this

Minutes 15–20: Sketch the Critical Sequence Diagram

Pick the most important flow (usually the happy path of the primary operation):
  POST /orders/{id}/confirm → PaymentService → Gateway → Ledger → Response

Add one failure branch:
  alt: Gateway declines → refund flow → order status = FAILED

Write this in Mermaid or on a whiteboard in the alt/else pattern from §3.2.

5.2 The LLD Interview Question: "Design a Payment Ledger"

Here is a complete 5-minute Mermaid sketch for this common interview prompt:

Pro Tip & Optimization

In an LLD interview, the interviewer is evaluating three things with your class diagram:

  1. Naming — are the entities named after domain concepts, not technical ones?
  2. Relationships — do you understand the difference between composition and association?
  3. Interfaces — have you inverted the dependencies so the domain doesn't couple to infrastructure? If your diagram passes those three tests, you are demonstrating senior-level architectural thinking.

6. Asynchronous Boundary Modeling

A common source of architecture diagram failures is treating async operations as synchronous. In a Node.js fintech service, every database call, every external API call, and every event emission is asynchronous. Sequence diagrams must make this explicit.

6.1 Modeling the Node.js Event Loop Boundary

Crucial Requirement

Always label the async boundary explicitly in sequence diagrams with a Note block. Without this, a reader cannot tell where the synchronous request-response cycle ends and where background processing begins.


7. Diagram Anti-Patterns to Avoid

Anti-Pattern Problem Fix
Everything in one class diagram Unreadable — 40+ nodes with crossed arrows Split by bounded context; one diagram per aggregate cluster
No stereotypes or labels Readers cannot tell interface from class from aggregate Always add <<interface>>, <<abstract>>, <<aggregate>>
Synchronous arrows for async calls Misleads readers about blocking behavior Use Note over blocks to mark async boundaries
Skipping the failure path Shows only happy path — critical for LLD review Always add at least one alt/else failure branch
Private implementation details Diagrams become maintenance burden Show only public contracts and key state fields
No reading direction Readers scan randomly — mental map is unclear Always set direction LR or direction TB intentionally

Summary

Concept Rule
Diagrams as code Mermaid in Markdown — committed to the repository, reviewed in PRs
Class diagram Model static structure: entities, interfaces, relationships, cardinalities
Sequence diagram Model dynamic behavior: actor lifelines, async boundaries, failure branches
Relationship arrows <|-- (inheritance) · <|.. (implementation) · --> (association) · o-- (aggregation) · *-- (composition)
alt/else The single most important Mermaid block for LLD interviews — models conditional flows
Interview framework 0–5 min: clarify · 5–15 min: class diagram · 15–20 min: sequence diagram · 20+ min: code
Async boundaries Always mark with Note over — never draw async operations with synchronous arrows

What's Next

In Part 6, we move from drawing architecture to enforcing it. SOLID principles are not abstract ideals — each one has a mechanical, compiler-enforced expression in TypeScript 5+. Part 6: SOLID Principles: Structural Foundations (S, O, L) dismantles the 60-line payment switch statement, builds type-safe strategy registries with satisfies, and proves Liskov violations at compile time with --strictFunctionTypes.

Research & Synthesis Note

This article was developed with AI-assisted deep search, specification cross-referencing, and technical research synthesis.

#TypeScript#UML#Mermaid#Architecture#LLD Interview#System Design
Siddhant Deval

Written by Siddhant Deval

Senior Full-Stack Engineer building high-scale architectures, browser performance engineering systems, and SaaS platforms.