The 100 ms budget
Latency targets a team can hold, set in design review, not after a bug.
Speed is a feature people feel before they see it. Nobody files a bug that says “the button felt slow”; they just trust the product a little less. By the time slowness shows up in a ticket, it has usually been there for months.
A budget makes the feeling measurable, early enough to act on it.
Why 100 ms
The number is old and well tested. Research on response times since the 1960s, summed up by Jakob Nielsen, puts the limits at about 0.1 second for a response to feel instantaneous, 1 second for a flow of thought to stay unbroken, and 10 seconds before attention is lost.
Google’s Core Web Vitals set a similar line for the web: an Interaction to Next Paint of 200 ms or less counts as good. Holding your own work to 100 ms leaves headroom for the slower phone, the busier main thread and the network you don’t control.
Set it in design review
Most latency is designed in, not coded in. A screen that waits for three requests before it shows anything was drawn that way. So the budget belongs in the design review, as one question asked of every interaction:
What does the user see in the first 100 ms after they act?
The answer doesn’t have to be the final result. It can be a pressed state, an optimistic update, a skeleton or a progress indicator. It has to be something, and it has to be drawn before it is built.
Measuring it
A budget nobody measures is a wish. Field data (Interaction to Next Paint from real users) tells you where you stand; the browser’s Performance panel tells you why. During development, a few lines are enough to flag slow interactions as they happen:
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.warn(`${entry.name}: ${Math.round(entry.duration)} ms`);
}
}).observe({ type: 'event', durationThreshold: 100, buffered: true });When the budget breaks
It will. The point of a budget is not that it never breaks; it is that breaking it is visible and has an owner. When an interaction goes over, there are three moves, in this order:
- Show something first: give feedback before the work, not after it.
- Do less: question whether the work is needed on this interaction at all.
- Do it later: split long tasks and yield to the main thread, so input is never stuck behind them.
What doesn’t work is a ticket in a tech-debt column. Treat a broken budget like a bug, because to the person waiting, it is one.
What it caught
[TEXT: a real example: an interaction the budget caught in review, and what changed. [N] ms before, [N] ms after]