Speed Patterns octocat github link burger menu

Optimistic Rendering

By Alexander Chernyshev · · Assisted by AI

When a user performs an action whose result is highly likely to succeed, you don't have to wait for the server to confirm before showing the new state. Render the success state in the UI as soon as the input lands — and reconcile silently in the background.

The Problem

Many user actions involve a server round-trip: liking a post, adding an item to a cart, posting a comment, reordering a list, marking a task done. The natural implementation waits for the server to respond before updating the UI:

  1. User clicks
  2. UI shows a spinner or disabled state
  3. Network request goes out
  4. Server processes and replies
  5. UI finally updates to reflect the new state

The user sits through every step. Even when the request succeeds in 200ms, that's 200ms of "waiting for the heart to fill in" or "waiting for the item to appear in the cart" — a delay between cause and effect that feels much longer than the same number of milliseconds spent doing nothing.

Solution

Render the new state immediately, as if the server had already responded successfully. Send the request in parallel and reconcile when the real response arrives. If it fails, roll back and surface a clear failure message.

Two flows side by side. Left, labeled 'pessimistic': click → spinner → wait → success state. Right, labeled 'optimistic': click → success state immediately, with a small note 'reconciles in background'.
Render the success state now, reconcile later

The user perceives the action as instantaneous because, from their point of view, it is instantaneous. The work of synchronizing with the server happens out of sight.

Where this works well

In every case, the operation has a high success rate, the new state is well-defined locally, and the user has more work they want to do without waiting.

Where this doesn't work

Why This Works

Latency that the user can't see has a much smaller effect on perceived performance than latency they can see. By rendering the result before the round-trip completes, the round-trip stops being part of the user's experience of the action. The wait still exists technically, but it stops being a wait.

Optimism only works because most operations succeed. When the failure rate is low enough — well under a percent for many UI actions — paying the rare cost of rolling back is a much better trade than paying the round-trip cost on every successful action.

Guidelines

Related Patterns

Technical Implementation

Most modern UI frameworks have first-class support for this pattern:

The shape of the implementation is always the same: apply a local state change immediately; fire the request; on success, replace the local state with the server's; on failure, undo the local state and surface an error. The framework abstractions just package those steps.

Resources