>soren hale — frontend developer
// Writing
The last hundred milliseconds
Getting a page from fast to instant is a different job from getting it from slow to fast.
- to read
- 2 min
- published
- 2026-09-18
- filed under
- Performance

Most performance work is removal. You find the two megabyte bundle, the blocking font, the image nobody sized, and you take them away. That gets a page from four seconds to one, and it is satisfying work because every change shows up on the chart.
The last hundred milliseconds are not like that. Nothing is obviously wrong any more. The page is already fast by any score you care to run, and it still does not feel instant.
Measure the wait, not the load
People do not experience your load event. They experience the gap between wanting something and seeing it. So I measure three moments: the first thing they can read, the first thing they can tap, and how long that first tap takes to answer.
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.duration > 100) report(entry.name, entry.duration)
}
}).observe({ type: "event", buffered: true, durationThreshold: 40 })
Forty lines of this in production told me more than a month of lab runs. The slow interaction was never the one I would have guessed.
Spend the budget on purpose
- Put the answer in the first response, even if it is a cached one.
- Hydrate the thing under the thumb first.
- Let everything else arrive late and quietly.
On the Northwind checkout the pay button was the last thing to become interactive, because it sat at the bottom of the component tree. Moving it to the front of the queue cost one afternoon and was worth more than the previous two weeks.
Know when to stop
Fast is a number. Instant is a feeling, and it starts at about a hundred milliseconds.
Below that line people stop noticing, so I stop too. The work is boring and specific, which is why it is rarely done, and why it is worth a lot to the few products that do it.
// Writing
The last hundred milliseconds
Getting a page from fast to instant is a different job from getting it from slow to fast.
- to read
- 2 min
- published
- 2026-09-18
- filed under
- Performance

Most performance work is removal. You find the two megabyte bundle, the blocking font, the image nobody sized, and you take them away. That gets a page from four seconds to one, and it is satisfying work because every change shows up on the chart.
The last hundred milliseconds are not like that. Nothing is obviously wrong any more. The page is already fast by any score you care to run, and it still does not feel instant.
Measure the wait, not the load
People do not experience your load event. They experience the gap between wanting something and seeing it. So I measure three moments: the first thing they can read, the first thing they can tap, and how long that first tap takes to answer.
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.duration > 100) report(entry.name, entry.duration)
}
}).observe({ type: "event", buffered: true, durationThreshold: 40 })
Forty lines of this in production told me more than a month of lab runs. The slow interaction was never the one I would have guessed.
Spend the budget on purpose
- Put the answer in the first response, even if it is a cached one.
- Hydrate the thing under the thumb first.
- Let everything else arrive late and quietly.
On the Northwind checkout the pay button was the last thing to become interactive, because it sat at the bottom of the component tree. Moving it to the front of the queue cost one afternoon and was worth more than the previous two weeks.
Know when to stop
Fast is a number. Instant is a feeling, and it starts at about a hundred milliseconds.
Below that line people stop noticing, so I stop too. The work is boring and specific, which is why it is rarely done, and why it is worth a lot to the few products that do it.
// Writing
The last hundred milliseconds
Getting a page from fast to instant is a different job from getting it from slow to fast.
- to read
- 2 min
- published
- 2026-09-18
- filed under
- Performance

Most performance work is removal. You find the two megabyte bundle, the blocking font, the image nobody sized, and you take them away. That gets a page from four seconds to one, and it is satisfying work because every change shows up on the chart.
The last hundred milliseconds are not like that. Nothing is obviously wrong any more. The page is already fast by any score you care to run, and it still does not feel instant.
Measure the wait, not the load
People do not experience your load event. They experience the gap between wanting something and seeing it. So I measure three moments: the first thing they can read, the first thing they can tap, and how long that first tap takes to answer.
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.duration > 100) report(entry.name, entry.duration)
}
}).observe({ type: "event", buffered: true, durationThreshold: 40 })
Forty lines of this in production told me more than a month of lab runs. The slow interaction was never the one I would have guessed.
Spend the budget on purpose
- Put the answer in the first response, even if it is a cached one.
- Hydrate the thing under the thumb first.
- Let everything else arrive late and quietly.
On the Northwind checkout the pay button was the last thing to become interactive, because it sat at the bottom of the component tree. Moving it to the front of the queue cost one afternoon and was worth more than the previous two weeks.
Know when to stop
Fast is a number. Instant is a feeling, and it starts at about a hundred milliseconds.
Below that line people stop noticing, so I stop too. The work is boring and specific, which is why it is rarely done, and why it is worth a lot to the few products that do it.
// Start a project
Tell me what you are building.
Three quick picks so the first reply is useful. You finish the message on the contact page.
// Start a project
Tell me what you are building.
Three quick picks so the first reply is useful. You finish the message on the contact page.
// Start a project
Tell me what you are building.
Three quick picks so the first reply is useful. You finish the message on the contact page.