Tearing in concurrent UI

Slap yourself if

You assume a render either fully happens or doesn’t happen at all.

Why this exists

Tearing exists because modern UIs allow rendering work to be paused, resumed, or interleaved. When state is read at different times during the same visual update, consistency is no longer guaranteed.

Mental model

Rendering is no longer an atomic snapshot. If multiple parts of the UI read shared state at different moments, the screen can represent multiple realities at once.

  • The renderer begins work using a snapshot of state.
  • State mutates while rendering is in progress.
  • Some components read the old state, others read the new one.
  • The committed UI reflects an impossible combination of values.
  • Derived values disagree across components.
  • Lists and detail views fall out of sync.
  • Visual glitches that disappear on re-render.
  • Bugs that only appear under load or slow devices.

Tearing is a concurrency bug where different parts of the UI render against different versions of state in the same commit, producing an inconsistent visual result without any single incorrect update.

  • Shared mutable state read during render
  • External stores without snapshot guarantees
  • Assuming render order implies state consistency
  • Ignoring concurrent rendering semantics

Deep dive

Requires Pro

Premium deep dives include more internals, more scars.

How concurrent rendering enables tearing

From visual glitch to broken invariants

Why snapshotting isn’t free

Recognizing tearing in the wild