Skip to content
Skip to content
Skip to content

Writing

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
A brass clock and a sealed envelope on a dark desk

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.

ts
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

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
A brass clock and a sealed envelope on a dark desk

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.

ts
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

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
A brass clock and a sealed envelope on a dark desk

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.

ts
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

Three quick picks so the first reply is useful. You finish the message on the contact page.

What do you need?

Rough budget

brief.tsdraft, not sent

Brief so far: nothing picked yet

or write to hello@sorenhale.dev

Nothing is sent from this page. Your picks are kept in this browser tab and wait for you on the contact form.

Start a project

Three quick picks so the first reply is useful. You finish the message on the contact page.

What do you need?

Rough budget

brief.tsdraft, not sent

Brief so far: nothing picked yet

or write to hello@sorenhale.dev

Nothing is sent from this page. Your picks are kept in this browser tab and wait for you on the contact form.

Start a project

Three quick picks so the first reply is useful. You finish the message on the contact page.

What do you need?

Rough budget

brief.tsdraft, not sent

Brief so far: nothing picked yet

or write to hello@sorenhale.dev

Nothing is sent from this page. Your picks are kept in this browser tab and wait for you on the contact form.

Footer

Local time, Oslo

Footer

Local time, Oslo

Footer

Local time, Oslo

Create a free website with Framer, the website builder loved by startups, designers and agencies.