Frontend Patterns

Pattern

Optimistic Update

Update UI immediately with expected results before server confirmation for perceived speed.

Optimistic Update

Problem

UI freezes or shows spinners after every user action, waiting for server confirmation. Simple interactions like liking a post, adding to cart, or marking items complete feel sluggish and unresponsive. Users perceive the app as slow even when the network is fast.

Solution

Update the UI immediately assuming operations will succeed, then rollback if they fail. This creates responsive interfaces that feel instant while handling errors gracefully.

Example

This example shows optimistic updates where the UI is immediately updated before the server responds, with automatic rollback if the operation fails.

const { mutate } = useMutation(updateTodo, {
  onMutate: async (newTodo) => {
    // Immediately update the UI before server responds
    // User sees instant feedback without waiting
    queryClient.setQueryData('todos', (old) => [...old, newTodo]);
  },
  onError: (err, newTodo, context) => {
    // If server rejects, rollback to previous state
    queryClient.setQueryData('todos', context.previousTodos);
  }
});

Benefits

  • Makes interactions feel instant by not waiting for server confirmation.
  • Dramatically improves perceived performance and user satisfaction.
  • Reduces visual friction from loading spinners and disabled buttons.
  • Creates responsive interfaces that match user expectations for speed.

Tradeoffs

  • Adds complexity with rollback logic when operations fail.
  • Can confuse users if optimistic updates are rolled back frequently.
  • Requires careful state management to handle conflicts and race conditions.
  • May show incorrect data temporarily if the server rejects the operation.
Stay Updated

Get New Patterns
in Your Inbox

Join thousands of developers receiving weekly insights on frontend architecture patterns

No spam. Unsubscribe anytime.