Skip to main content
When a user clicks a button, the result should feel instant — even if the underlying mutation takes 200ms. Optimistic updates show the predicted result immediately and reconcile if the server disagrees.

When to use

✅ Toggling a state

Mark task done; like a post; star a comment.

✅ Adding to a list

Send a chat message; add a todo.

❌ Stateful side effects

Charging a credit card. Don’t predict success — wait.

❌ Operations that often fail

Form submissions with strict validation. Failure recovery is more painful than the wait.

Pattern with Convex

Convex’s useMutation doesn’t have optimistic updates built in. Use Zustand or component state for the optimistic layer:
When the mutation succeeds, tasks re-fetches via reactive sync; the optimistic flag is dropped, and the displayed value is now the real one.

Reconciliation on failure

If the mutation fails, the optimistic toggle should revert:
The query data is the source of truth on disagreement.

Tips

For most CRUD apps, you don’t need optimistic updates. Convex mutations resolve in 50–200ms. The UI feels fast already.
Optimistic updates are most valuable on slow connections. The 200ms-on-fast-internet becomes 1000ms on a poor cell signal.

State management

Where the optimistic state lives.

Convex mutations

The underlying writes.

Real-time sync

What reconciles after.
Last modified on April 18, 2026