System Design Bits

Support the project

System Design Bits is free and always will be. If it helped, a coffee helps back.

Buy Me a Coffee QR codeBuy me a coffee

Frontend Design

A 9-step walkthrough to Frontend System Design

The same discipline as backend system design, pointed at a machine you don’t own.

Big Idea

A backend design grows outward: each step earns another box on the diagram. A frontend design doesn’t. The stack is the same nine times over: shell, router, components, store, cache, transport, storage. What each stage changes is who owns which part of it, how long the data inside it lives, and what the user is looking at while it’s still arriving.

So these nine stages are nine passes over one picture, not nine additions to it.

Walk It

Nine Stages, One Stack

Step through it. No stage adds a box after stage 3. Each one lights up the layers it governs, and the ones left grey are somebody else’s problem for now.

Frame
Build
Harden
Stage 1 of 9 · Frame · Frame the problem
The client stack at stage 1A user, on a deviceTHE CLIENT: YOUR CODE, THEIR CPUShell + RouterFRAMEUI componentsPAINTStoreCLIENT TRUTHCacheSERVER ANSWERSData clientEVERY CALL OUTWorkersOFF MAIN THREADPersistenceSURVIVES REFRESHCROSS CUTTINGSession / authTelemetrytouches every layer,owned by none of themNETWORK BOUNDARY: NOTHING ABOVE IT IS TRUSTEDServer / APIs
01

Only the two endpoints. A user, and something that has data. Everything between them is still a guess.

Who is on the other side of the screen, and on what device?

What you decide here
The tell that it’s done

You can name the one journey the whole design serves, and the device it has to feel fast on.

Stages 1 and 2 light almost nothing, and that is the argument. Neither one produces code, and they are the two that get skipped, because skipping them is the only way to start building immediately.

End of the nine stages

The Two Axes

Where Every Value On Screen Lives

Stage 4 is the one most designs lose, and it only ever asks two things: who owns this and how long does it live. Two questions make a plane, and each quadrant of it comes with its own instruction.

Ownership against lifetime← CLIENT OWNS ITSERVER OWNS IT →DURABLE ↑EPHEMERALYou have to persist it. Nobody else will.Cache it, and own the invalidation.Let it die with the render.Fetch it again. Don't store it.Theme preferenceURL / route stateUnsaved form draftScroll positionHover / focusSession / identityCached query resultFetched list in view

The quadrant decides the mechanism, not your preference for a library

Nothing here is a type of state. They are positions, and a value can move: an unsaved draft that starts in the bottom left and gets autosaved has crossed into the top left, which is the moment it becomes your job to keep it.

The Deliverable

Eight States, Not One

Stage 5 asks what is on screen before the data is. This grid is the whole answer to it: eight states, answered for every screen you ship, and a screen with one of them designed is a screen that isn’t finished.

A mockup only ever shows the first one — the data arrived, the list had items, nobody lost their connection. The other seven have no picture to copy, which is why they get discovered in production, one support ticket at a time.

Loading

and for how long before you say something

Success

the only one anyone designs

Error

transport, or domain: say which

Empty

never used it, versus nothing matched

Stale

shown, and labelled as old

Offline

what still works, stated plainly

Unauthorized

sign in, or you may not: two different screens

Pending

optimistic, and reversible

The Budget

What “Fast Enough” Actually Means

A budget is a number you agree on before you build, so that “is it fast enough” has an answer instead of an argument. Without one, every performance technique is optional and nothing can ever be called done, because there is nothing to be done against.

Four of stage 7’s numbers come with the line already drawn. These are the published Core Web Vitals thresholds, the same ones search engines and Lighthouse score you on, so the only question left is which side of them you land on.

Core Web Vitals thresholdsLCP2.5s4sLargest Contentful PaintINP200ms500msInteraction to Next PaintCLS0.10.25Cumulative Layout ShiftTTFB0.8s1.8sTime to First Bytegoodneeds workpoor

Good, needs work, poor. The boundaries are published, not chosen by you

LCP · Largest Contentful Paintgood ≤ 2.5s

How long until the biggest thing on screen, usually the hero image or the headline, has actually painted. The closest single number to "when does this page feel like it is here".

INP · Interaction to Next Paintgood ≤ 200ms

How long a tap or a keypress takes to produce a visible change. This is the one that decides whether the page feels alive or stuck.

CLS · Cumulative Layout Shiftgood ≤ 0.1

How much the page jumps around while it loads, scored rather than timed. Almost always an image, an ad or a font arriving without its space reserved.

TTFB · Time to First Bytegood ≤ 0.8s

How long the server takes to send the first byte of the response. Everything else on this list only starts counting after it.

The other five have no published threshold, so you have to pick a number and write it down. A budget you chose arbitrarily still beats no budget, because only one of the two can be exceeded. These are reasonable places to start arguing from.

JS bundle size~170KB compressed, first route

What has to arrive and run before the page works. Measure the route someone actually lands on, not the whole app.

Memoryflat after 10 minutes

The shape matters more than the number. A tab that climbs while you scroll a long list is leaking rows somewhere.

Dropped framesno task over 50ms

A frame is drawn every 16ms, so one long task on the main thread is visible as a stutter during a scroll or a drag.

API latencyp75, not the average

The average hides the slow quarter of your users. Budget the 75th percentile and the number stops lying to you.

Error ratea ceiling you alert on

Failed requests and caught exceptions per session. This one is not a target to hit, it is a line that pages somebody.

Measure them on the device from stage 1, not on your laptop. A budget met on a machine nobody in your requirements owns is not a budget, it is a screenshot.

Why This Exists

Why Frontend Design Needs Its Own Order

▸

Backend system design has a settled shape: boxes, arrows, and a request moving between them. Run that playbook on a frontend and you draw three boxes and stop, because the interesting parts aren't components, they're ownership and timing.

▸

The frontend's hard problems are the ones a topology diagram can't show: who owns this value, how stale is it allowed to be, and what is on screen while we find out.

▸

Most frontend design failures are not architectural. They are a state that nobody designed: the empty list, the expired token, the second tab, the request that came back after the user navigated away.

▸

And unlike a server, you don't control the machine your code runs on. The budget is set by the worst device in your requirements, which is why stage 1 has to name it.

The Difference

Same Discipline, Different Physics

BackendFrontend
The unit of designA service, and the contract around itA layer, and who owns the data crossing it
What the diagram showsTopology: what calls whatOwnership: who holds which truth, and for how long
Where scale bitesMany users hitting one systemOne user on one slow device, holding one tab open for hours
The failure you plan forA node dies and traffic reroutesThe network vanishes mid write and the user keeps typing
What you can't controlSomeone else's traffic spikeSomeone else's hardware, browser, and extensions
Who can read your codeNobody outside the VPCVirtual Private Cloud. The private network your backend lives in, unreachable from the public internet unless you deliberately open a door. Server code sitting inside one is never downloaded by anyone, which is why a secret can live in it and never in your bundle.Everybody, with devtools, in about four seconds

Common Mistakes

Ways These Nine Stages Get Misused

✕

Answering "design Figma" with a box diagram, when the whole question is how two people editing the same thing converge.

✕

Treating server data as client state, then spending the rest of the project syncing two sources of truth that were never meant to agree.

✕

Reaching for a WebSocket when the requirement was "fresh", not "live", and inheriting reconnect, ordering and resync for nothing.

✕

Designing only the success state, then discovering the other seven in production one support ticket at a time.

✕

Optimising renders before measuring, while the actual cost is an unsplit bundle and three fonts.

✕

Listing performance techniques without a budget, which makes every one of them optional and none of them checkable.

✕

Hiding a button for permissions and calling it authorization, when the endpoint behind it never checks.

✕

Walking through all nine stages as topics to mention rather than decisions to make, which produces a vocabulary demonstration instead of a design.

Key Points

What To Carry Out Of This

✓

The stack doesn't change; the ownership does. Stage 3 names the boxes once, and every later stage claims the ones it governs rather than adding new ones.

✓

Frontend design is state design. Lifetime and ownership are the two axes, and almost every disagreement about architecture is really a disagreement about one of them.

✓

"Fresh" and "live" are different requirements. Only one of them costs you a socket, reconnect logic, and event ordering.

✓

The eight UI states are the deliverable, not a checklist. A screen with one state designed is a screen that isn't finished.

✓

A budget makes performance checkable. Without a number, every technique is a suggestion and nothing can be said to be done.

✓

Nothing on the client is a security control. It can be a convenience over one, and that's the most it can ever be.

✓

Every stage has a tell. If you can't say what you walked away with, you named the stage instead of doing it.

Answered In Full

The Same Decisions, As Interview Questions

A stage names the decision; these are the mechanisms underneath it, each written out the way you would say it in the room. They open on the Q&A page and come back here when you close them.