· 1 min read

Why latency is a feeling

We ship milliseconds, but nobody experiences milliseconds. People experience whether a thing felt instant, whether a button felt like it heard them, whether the screen kept up with their thumb.

That gap, between fast and feels-fast, is where most of the work lives.

The dashboard lies a little

A p95 of 120ms looks great in a chart. But a chart averages away the moment that actually matters: the first tap, on a cold cache, on a tired phone, on hotel wifi. That one is the impression people keep.

So I stopped optimizing the average and started hunting the worst honest case:

// not "is it fast", but "when is it slowest, and who feels it"
const worst = samples.sort((a, b) => b.ms - a.ms).slice(0, 10)

Feel is mostly about honesty

A spinner that shows up after 100ms reads as “working.” The same spinner at 800ms reads as “broken.” The number barely moved. The feeling fell off a cliff.

Optimistic UI isn’t a trick to look faster. It’s a promise you intend to keep.

The fix is rarely a faster server. It’s usually telling the truth sooner: an optimistic update, a skeleton that matches the real layout, a transition that absorbs the wait instead of hiding it.

What I do now

  • Measure the cold, unlucky path, not the warm one.
  • Respond to input within a frame, even if the data isn’t ready.
  • Make waiting feel intentional, never frozen.

Fast is a number. Feels-fast is a craft. I care about the second one.