Skip to content
8 min read#frontend

Architecting Zustand Stores at Scale

Why one big store collapses as your React app grows — and the store-per-domain pattern I use instead. With real examples from a 40+ screen production app.

Architecting Zustand Stores at Scale

Zustand is a pleasure for small apps. One create() call, a hook, done. But the pattern that makes it addictive — a single global store — does not survive contact with a real product. After shipping a 40+ screen app on it, here's what I'd do on day one if I were starting over.

The problem with one big store

Every component subscribes to the same store. Every action — even a loading spinner toggle on a modal three routes away — is a candidate cause for a re-render on your home screen. You paper this over with selector functions and shallow, but the mental model is still *everything depends on everything*.

Selector discipline works for a while. Then a new teammate adds set({ ...state, ... }) somewhere, and you're back to spaghetti.

Store per domain

The pattern that held up for me: one store per bounded context. Auth, feature-flags, the active document, the command palette — each gets its own tiny create(). They never import each other.

// stores/useAuthStore.ts
export const useAuthStore = create<AuthState>((set) => ({
  user: null,
  signIn: async (email, pw) => {
    const user = await api.signIn(email, pw);
    set({ user });
  },
}));

Each store is small enough to hold in your head. Tests mock one store at a time. When a domain is gone, you delete the file.

Cross-store coordination

When two stores need to talk, the coordinator lives *outside* the stores — usually in a hook or a saga-like async function. Stores stay dumb. Orchestration is explicit.

Rules I enforce in code review

  • A store file is under 150 lines or it's too big.
  • No store imports another store.
  • Every action returns void or Promise<void> — never derived state.
  • Selectors are colocated with the component that uses them.

Closing

Zustand isn't Redux-lite; treat it that way and you'll reinvent every Redux footgun. Treat each store as a small, single-purpose module and it stays fun at scale.