Part 0 · 5 chapters · ~30 min

The Method

A frontend system is a set of numbers and the simplest design that meets them, revised each time a number grows past what the design can carry, with the trade-off named every time. This part is what makes frontend design its own discipline, the loop every part runs, the budgets the numbers are measured against, the five currencies a trade-off is paid in, and the nine systems ahead.

1

What a frontend system design is

the brief

"Design the transactions page. Ops needs to filter, sort and export. It should be fast."

That is a brief, not a design, and it is how every system in this course arrives. A frontend system design is the sequence of decisions that turns a brief into something that meets specific numbers on specific devices, revised each time a number grows past what the current design carries. The backend design disciplines apply (requirements, estimation, the simplest thing, the increment, the trade-off); the frontend adds the device's budgets: heap, main-thread time, bytes over the connection, decode time, and the milliseconds a person notices.

what makes it different from backend design
  1. The machine is the user's, not yours: a mid-range phone with a 4 GB heap limit shared with the DOM, one main thread, a 4G connection with 80 ms round trips, and a battery. You do not get to add a server.
  2. The budgets are perceptual: 100 ms to feel instant, 16.7 ms per frame, a layout shift the eye catches. Throughput matters less than latency at the moment of interaction.
  3. State is distributed across two machines (the server's truth and the client's copy) and sometimes more (other users, other tabs, offline queues), and the client is the one that can be wrong.
  4. Bytes are a cost paid per user per load, which makes "add a library" a design decision.
  5. The failure modes are visible: a frozen tab, a spinner, a jump, a stale number. The user sees the design's limits directly.
what the course does
  1. Nine systems, each from a brief and a set of numbers, grown through increments as the numbers change, with the trade-off named each time.
  2. The same loop every time (next chapter), so that after a few parts the loop is yours and the systems are examples.
  3. Mechanisms from the sibling courses: the browser course for the pipeline and budgets, the JS course for memory and parse, the algorithms course for windowing and diffing and scheduling, the React course for state and data. This course points at them rather than repeating them.
2

The loop: brief, questions, numbers, v1, the break, v2

Every part runs one loop. It is the Core Banking module's rounds applied to the client: a brief, the questions that pin it down, requirements with numbers, the simplest design that meets them, the number that breaks it (shown with arithmetic), the fix, and the cost of the fix. Then the next number. The design document is the sequence of rounds.

the steps
  1. The brief. Vague by nature: what, for whom, with adjectives. Accept it as the starting point; do not design from it.
  2. The questions. How many (rows, users, items, messages) today and in two years. How big (bytes per thing). How fresh (seconds, minutes, never). How fast (the slowest acceptable response per action). On what (devices, connections, browsers). What happens when it is wrong (the cost of staleness or a lost update). What must work offline. These are the first deliverable.
  3. Requirements with numbers. Functional (what it does) and non-functional with a number each (how much, how fast, how fresh, how reliable). "Fast" is replaced by "filter in under 200 ms at 10M rows on an office laptop".
  4. v1. The simplest design that meets today's numbers. Often embarrassingly simple: fetch everything, hold it in memory, render a window. Write down which number breaks it.
  5. The break. One number grows. Show, with arithmetic, how v1 fails: bytes × rows exceeds the heap; items × nodes exceeds the DOM budget; messages × size exceeds the connection; work × time exceeds a frame. Name the symptom the user would see.
  6. v2 and its trade-off. The smallest change that carries the new number, with the cost named in one of five currencies (next chapter). Then v2 is the new v1, and the loop continues.
  7. Stop when the numbers stop growing or when the next trade-off costs more than the number is worth. Not every system needs v5.
worked numbers
the shape of a round, as the parts write it:

  number:     10,000 rows → 2,000,000 rows
  v1:          fetch all, filter in memory, virtualised table
  break:       2M × 200 B = 400 MB JSON → ~1.2 GB parsed → the tab dies; before that, a 60 s fetch
  v2:          server-side filter/sort/paginate; the client holds one page
  pays:        +100 ms per filter (latency) · a query protocol + indexes (complexity, money) · no cross-page client ops (capability)
  next break:  "select all" across pages; freshness under a minute with 200 users; an export of 100k rows

one number, one break, one fix, one cost. the final design is the sum.
THE LOOP
brief to numbers to v1 to the break to v2, and round again
swipe the figure sideways, or tap expand for full screen
1/6
brief → questions
The brief: "a table of transactions for ops staff; filter, sort, export". Vague on purpose. The first job is the questions: how many rows today and in two years; how many concurrent users; how fresh must it be; what devices; what is the slowest acceptable interaction.
3

The numbers, and the budgets they are measured against

A frontend design is decided by comparing the brief's numbers to the device's budgets. The budgets are physical constants of the platform (with a device-class multiplier), and knowing them is what lets you say "v1 works until 2M rows" before writing v1.

BudgetLaptop (office)Mid-range phoneWhere it bitesCourse
Heap usable by your data~1 GB of a 4 GB limit (DOM and framework take the rest)~300 MB of a 1 to 2 GB limitRows in memory; parsed JSON is ~3× its text sizeJS P5
JSON parse~100 MB/s~20 MB/sA 50 MB payload is 2.5 s of main thread on a phoneJS P6
NetworkFibre: 100+ Mbps, 1 to 5 ms RTT4G: 10 to 50 Mbps, 50 to 100 ms RTT; 3G worsePayload size per interaction; dependent requestsBrowser P1
Main thread per frame~10 ms of 16.7 after the browser's work~5 to 8 ms (slower CPU, same frame)Anything per frame: scroll handlers, live updates, animationsBrowser P6
Interaction response100 ms instant · 200 ms INP good · 1 s with feedback · 10 s lostEvery click, keystroke, dragBrowser P12
DOM nodes~10k before layout is visibly slow~3kLists, tables, trees without windowingAlgorithms P1
Layout and paint areaFull-viewport repaint ~1 to 5 ms; with blur or shadow ×10Live updates that invalidate large areasBrowser P5, Algorithms P4
Image decode12 MP JPEG ~15 ms~40 to 60 msGalleries; many images in one frameBrowser P11
Worker startup and messagingStart ~30 to 50 ms; clone ~0.5 GB/s; transfer O(1)Offloading compute; chunked pipelinesBrowser P7
WASMStreaming compile ~tens of MB/s; near-native loops; a call boundary ~nsCodecs, parsers, numeric kernelsBrowser P7
StorageIndexedDB writes ~MB/s; OPFS sync access much faster; localStorage 5 MBOffline data; large cachesBrowser P8
Concurrent connections6 per origin (HTTP/1.1); multiplexed (HTTP/2, 3); one WebSocket is one connectionReal-time fan-in; many small requestsBrowser P1, FSD M8
the move
For each number in the brief, find the budget it is measured against and compute the ratio. Under 10%: v1 is fine. Near 100%: this is the first break. Over: v1 must already be v2.
THE NUMBERS A FRONTEND DESIGN NEEDS
and the budget each one is measured against
swipe the figure sideways, or tap expand for full screen
1/6
data
Data: rows (or items, messages, points); bytes per row; growth rate; freshness required. Compared against: the tab's heap (hundreds of MB usable; part of a 2 to 4 GB limit shared with the DOM), the JSON parse rate (~100 MB/s on a laptop, 20 on a phone), and the network (a 10 MB payload is 2 s on 4G at best).
4

Naming the trade-off

An increment that is not costed is a surprise waiting for production. Every increment in this course is written as a sentence that names what it buys (the number) and what it pays, in one or more of five currencies. The currencies are the same for every system; the amounts differ.

the five currencies
  1. Bytes: bundle, payload, assets. Paid by every user, every load, against their connection and parse budget.
  2. Complexity: code, states, protocols, failure modes the team now owns. Paid forever, against the team's capacity to understand it.
  3. Consistency: what the user may see that is not true: stale, optimistic, merged, locally validated. Paid in trust, against the cost of being wrong for this data.
  4. Latency: round trips and critical-path work added. Paid per interaction, against the 100 / 200 / 1,000 ms thresholds.
  5. Money: servers, bandwidth, pipelines, infrastructure, people. Paid by the business, against what the feature earns.
the sentence
  1. "vN buys ___ (the number) and pays ___." With each blank filled by a currency and an amount: "+100 ms per filter", "a 300 KB library", "one-minute staleness on counts", "a transcoding pipeline at ~$X per hour of video".
  2. If a blank cannot be filled, the increment is not designed. If the amount is unknown, measure it (a spike, a benchmark, a quote) before committing.
  3. If the cost exceeds the number's value, do not build it; find a cheaper increment or accept the limit. "We will not support select-all over 1M rows; the UI says so" is a design.
the trade-offs this course meets most
  1. Client memory versus server round trips (M1, M6, M7): hold more locally for instant interactions, or fetch per interaction for scale.
  2. Main thread versus worker boundary (M2, M4): responsiveness for the cost of serialisation and a message protocol.
  3. Bytes versus quality versus decode (M3): smaller images cost quality; better codecs cost decode time or a shipped decoder.
  4. Consistency versus availability (M5, M7, M8): show something possibly stale, or show nothing until sure.
  5. Latency versus correctness (M9): check locally and show now, or wait for the server and show the truth.
WHAT EVERY INCREMENT COSTS
the five currencies a frontend trade-off is paid in
swipe the figure sideways, or tap expand for full screen
1/6
bytes
Bytes: client bundle, payload per request, assets. Paid by every user on every load. A virtualisation library is 10 KB; a charting library 300 KB; a WASM codec 2 MB. The budget: the user's connection and the parse time (the JS course part 1).
5

The nine systems, and how to read them

the parts
  1. M1 Data-intensive: a transactions table from 10k rows to 10M. Memory, pagination, normalisation, server state, cross-page selection, exports, freshness.
  2. M2 Compute-intensive: a report generator and a file parser that must not freeze the tab. Slicing, workers, WASM, progress, cancellation, memory limits.
  3. M3 Media-intensive: a photo and video product. Responsive images, uploads with resumability, client-side transcoding versus a pipeline, adaptive streaming, decode budgets.
  4. M4 Visualisations and dashboards: live charts at 60 fps. Canvas versus SVG versus WebGL, data reduction, update batching, layers.
  5. M5 Change-intensive: a collaborative document. Last-writer-wins to OT to CRDT, presence, conflict UI, offline edits and sync.
  6. M6 Lists at scale: a million-item list with selection, variable heights, infinite scroll, keyboard navigation, stable identity across refetches.
  7. M7 Social media: a feed. Ranking the client sees the end of, fan-out, infinite feeds with media, notifications, the social graph on the client.
  8. M8 Real-time: the subscription layer under M5, M7 and M9. WebSockets versus SSE, backpressure, reconnection, ordering, presence, at 100k concurrent.
  9. M9 Trading: order books and price streams at tens of updates per second per instrument, order entry with client-side risk checks, a latency budget per hop, degraded modes.
how to read a part
  1. Read the brief and write your own questions before reading the course's. Compare.
  2. Do the arithmetic for each break yourself from the numbers given; the figures show the course's.
  3. At each v2, write the trade-off sentence before reading it.
  4. Then apply the loop to a system you own: its brief, its numbers, its v1, its next break. That is the exercise at the end of every part.
the pointer
M1 starts with the brief from this part's first chapter and runs it to ten million rows. It is the longest part because the data-intensive case is where most frontend systems first meet their numbers.