Performance
The milliseconds are architecture showing up as timing
Aug 17, 2026 · 1 min read
Most performance conversations start too far down the stack. Someone opens Lighthouse, trims an image, splits a bundle, and hopes the number moves. Sometimes it does. Often the page is still slow in the only way that matters: the user is waiting.
That wait is usually architecture. A page requested data it did not need yet. A client component fetched on mount what the server already knew. A layout waited on a waterfall of dependencies that could have been parallel, or not loaded at all.
Timing is a trace
A waterfall is not a frontend curiosity. It is a diagram of ownership. If four requests must complete before the first useful pixel, the system decided those four things were on the critical path. Maybe they should be. Often they should not.
The useful question is not "how do we make this query faster?" It is "why is this query on the path to first paint?"
Rendering is a decision
Next.js makes rendering choices visible: static, server, client, cached, fresh. That is a gift if you treat it as architecture, and a trap if you treat it as a default.
Static pages should be static. Personalized pages should not download an application to discover they needed one database read. Client JavaScript should exist because the browser has work to do, not because a component was easier to write that way.
What to change
When we look at a slow route, we look at:
- What must exist for the first paint
- What can stream or wait
- What is being computed in the browser that could have been computed once
- What is being fetched twice because two components did not share a boundary
The milliseconds are not a mystery. They are the system describing itself. Read the timing. Then change the architecture it implies.