Mutations and Optimistic Updates
Learn to model server writes as coordinated state transitions and use optimistic updates so the UI feels instant while staying correct and trustworthy.
Most React teams become comfortable once reads are solved. Data is fetched, cached, paginated, and rendered predictably. But the moment users are allowed to change data, like a post, update a profile, or reorder a list, the architecture often regresses. Writes are handled as special, fragile moments in the UI: buttons are disabled, spinners appear, and entire sections wait for the server to respond before anything changes.
This pattern feels “safe,” but it introduces a different class of problems. The UI becomes latency-bound: every interaction waits on the network, even when the user’s intent is obvious. Lists flicker because teams refetch aggressively after every write. Shared state drifts out of sync because multiple components update at different times. Error handling becomes destructive; a failure often means tearing down UI state and rebuilding from scratch.
The deeper issue isn’t just performance, it’s state ownership. In many codebases, the UI has no clear contract for what it should represent while a write is in flight. Is the change pending? Is it optimistic? Is it confirmed? Without a shared system-level answer, components invent local flags and ad-hoc temporary state, and rendering becomes tightly coupled to request lifecycles instead of the data model.
React Query’s mutation model, especially optimistic updates, exists to address this gap. Instead of treating writes as blocking events that freeze the UI, it treats them as coordinated transitions in server state. The cache becomes the place where intent, assumption, confirmation, and rollback are managed, so components can render a consistent snapshot without micromanaging the write process.
The above diagram contrasts two timelines. In the first, a user action triggers a write, the UI enters a waiting state, and the screen updates only after the server responds. In the second, the cache applies an optimistic update immediately, the UI reflects the change right away, and the server response later either confirms the change or rolls the cache back to its previous snapshot.
Treating mutations as state machines
A mutation represents an intent to change the server truth. Unlike queries, which describe what exists, mutations describe what should become true. The key architectural decision is whether the UI waits for that truth to be confirmed or ...