The first response carries extra init cost and is usually slower than steady state
Aliases: cold start · first-hit penalty · warmup cost
What it is
The same button, the first press today, has to open a connection, fetch a module, fill a cache, run auth; the fifth press already has those. First response therefore almost always carries cold-start overhead, a slice slower than later steady-state response. The slowness is not “this feature is slow”. It is “this attempt is paying the cover charge”. Treat first and steady as one kind of performance and you will neither explain the complaint nor aim the fix.
This is about response (the result coming back), not the first touch queued behind a jammed main thread. That queue is a different ledger.
Why it happens
The cover charge is one-shot work: TLS handshake, route discovery, code-split download, deserialisation, a full query on an empty cache, runtime compile. It lands on the first request, not the second. Engineering “mean response time” folds the first and the next nine into one mean: the first is diluted, steady state is dragged, neither side looks like itself.
The cost also infects across entries. The first network request after opening the app often pays handshake for the whole session; the first settings page often pays download for the whole settings bundle. So “this button is slow” is sometimes not the button’s fault. It happened to be first in the session.
Studying it
Report delay for the 1st, 2nd and nth call of the same operation separately, crossing cold start (kill process, clear cache, new session) with warm. See which layer ate the extra time on first: handshake, code load, or business query.
Independent variables: cold versus warm start, ordinal call, whether dependent modules were already loaded. Dependent variables: split duration (handshake / download / business), ratio of first to steady.
Labs that tap once to “prepare” before measuring will measure the overhead away. Field logs need a session-ordinal on the request, or the average will always look “fine”.
Where it stops holding
Purely local UI with no lazy load can make first and steady almost equal; the leaf is faint. One-shot tools with no server (a calculator) have no cover charge. Server work that is cold every time (a large model on every call) has no steady state to compare — every call is “first”. CDN and edge cache turn “first” into “first on this node”; the same user pays the cover again in another city.
Applying it
- Split performance reports into “first in session” and “later in the same session”. Do not only ship a mixed mean.
- When chasing “this button is slow”, ask whether it was first in the session; if so, inspect handshake and bundle load before the button’s business logic.
- Lift cover charges that can be lifted: warm the connection, put the critical split in the first packet, so the first hit pays less.
- How to check: kill the process, open, do the target action at once, record duration; do it four more times in the same session. The first should name the extra slice as handshake, download or query. If that slice cannot be named, you are still looking at a mixed mean.
Related
- Same group: I1.07.2 Patience is higher for the first action than for later repeats · I1.07.3 Warmup or preload can move first-hit cost to a moment the user does not feel · I1.07.4 A large first–steady gap makes users misjudge overall performance
- Nearby: I1.04 Input latency and tracking · I2.04 Prefetch and preload
- Search terms:
cold start·first response·steady-state latency