May 17, 2026

When the screen has to stay where you expect

Scrolling backwards through a long conversation is one of the hardest screens in any chat-style app — a few small promises that compound into something genuinely difficult.


Scrolling backwards through a personal forest longer than fits in memory is the hard problem every chat-style app eventually has to solve.

The promise is small but inflexible:

  • Newest message at the bottom when you open the screen.
  • Scrolling up loads older messages without anything jumping.
  • New messages arrive, but never push what you’re looking at out of view.
  • A message you find via search lands in the right place — not under the chrome, not behind the keyboard.

Each one is straightforward on its own. Holding all of them at once, while the user is actively scrolling, is the hard part.

Why it cascades

Variable-height messages change the scroll math. The scroll math changes which message sits at the visible bottom. Which message sits at the visible bottom decides whether a new arrival is welcome or intrusive. Whether the arrival is welcome decides whether you snap, queue, or do nothing. Whether you snap depends on whether anything else just snapped.

A bug in one layer manifests in another. The chat screen is the cascading-renders problem most apps eventually face.

What we ended up with

A bounded window of messages in memory. Scrolling backwards fetches older pages and evicts the newest; scrolling forward fetches the other direction. Real-time arrivals while you’re scrolled away wait behind a small “new messages” cue. The anchor — what sits at the bottom, where a search lands — is derived from the chrome’s actual size each render, not a hand-picked number.

None of these are individually clever. The clever part is making them hold together while you’re using the screen.


← All posts