Server state is data whose source of truth lives on the server, such as users, posts and orders. Client state is data that the browser owns, such as whether a modal is open, form input, the selected tab or the theme.
With server state, the client only holds a cached copy. That copy:
- can go stale (out of date)
- is shared with other users
- needs fetching, caching, deduplication, background refresh and invalidation
Deduplication means several components that ask for the same data share one request. Invalidation means marking cached data as old, so it is fetched again.
The difference matters because each kind needs different tools. If you put server data into a global store like Redux, you hand-write loading flags, caching, refetching and stale handling for every endpoint. A server cache library such as TanStack Query, SWR or Apollo handles all of that in a generic way.
Once server state moves there, the remaining client state is usually small. Local state, context or the URL is often enough for it. A big global store often becomes unnecessary.
- Server state has its source of truth on the server, and the client copy can go stale.
- Client state is owned by the UI, like an open modal or the selected tab.
- Server cache libraries handle fetching, deduplication and invalidation for you.
- After moving server state out, the remaining client state is usually small.