This closing episode compares Pinia with Vuex 4, manual composables, and signal-based stores like Legend-State and Valtio, builds a 2026 Vue state management decision framework, recaps the journey of episodes 0-21, and looks at the direction of Vue's evolution with Vapor Mode and signals.

The long journey is almost over. Before closing, it's important to see Pinia not as the only answer, but as the right choice in the right context. This final episode gives you the map for making that decision.
Episode 22 covers comparisons of Vue state management, building a decision framework for 2026, recapping the journey of episodes 0-21, and looking at Vue's evolution with Vapor Mode and signals.
Vuex 4 is Pinia's predecessor: one store, mandatory mutations, verbose. Pinia wins with a smaller API, automatic type safety, no mutations, and official support. Vuex is only used for legacy projects — there's no strong reason to choose it for new ones.
The most noticeable API difference is the removal of mutations. In Vuex, every state change has to go through mutations for the sake of clarity; in Pinia, actions change state directly, and DevTools time-travel still works because changes are recorded automatically. Without the mutation boilerplate, store code shrinks by almost half without losing traceability. For teams already stuck on Vuex, a gradual migration is also possible because both can run side by side in one project during the transition.
Manual composables with a global ref are enough for small state. They fall short in DevTools, the plugin system, and testing tooling. The rule of thumb: composables for local state and reusable logic; Pinia for state shared across components.
The fundamental difference lies in the surrounding infrastructure, not the API itself. A global ref works, but there's no standardized way to trace who modifies it, no history, no plugins, and no way to disable the store during testing. Pinia covers all of that: DevTools shows every store, $patch records mutations, plugins extend capabilities, and createTestingPinia makes it possible to test components in isolation. For one or two global values, this difference isn't felt; for a full application, it's a differentiator.
Libraries like Legend-State and Valtio bring signal primitives for granular updates. This approach is appealing for extreme performance, but the ecosystem and tooling aren't as complete as Pinia's. Signals work very well when an app has thousands of nodes changing independently — for example editors, real-time dashboards, or games — where granular updates save unnecessary renders. But for the majority of business applications, Pinia's overhead is already small, so signals' advantage is rarely felt in practice.
The choice between them is better seen as a spectrum than a battle: Pinia wins in developer experience, community support, plugins, and testing; signals offer fine control over when an update is propagated. You can also combine them — keeping part of the state in signals for very dynamic sections, while the main domains keep using Pinia — as long as the interface between them is clear.
const decision = {
newProjectVue3: 'Pinia',
legacyVue2: 'Vuex 4',
tinyLocalState: 'composable',
maxGranularity: 'signal-based',
}const decision = {...} summarizes the practical decisions: new Vue 3 projects use Pinia, legacy stays on Vuex, local state is fine as a composable, and signals only when maximum granularity is truly needed.
As a final guide:
ref or a composable.This division is what modern production teams use: Pinia handles client state, a server-state library handles APIs, and the two coordinate without overlap.
As a real example, an e-commerce dashboard could divide responsibilities like this: useCartStore and useUiStore use Pinia for user interactions; useProductsQuery from Colada handles the product list and cache invalidation; preferences like the theme are persisted to localStorage using the plugin from episode 9; and all of those parts are tested with @pinia/testing. No single library is forced to handle two categories at once — every layer uses the tool designed for its task.
From episode 0, you've covered: environment setup, history and architecture, the first store, Options vs Setup stores, state and reactivity, getters, async actions, the plugin system, persistence, DevTools, SSR, composing stores, performance tuning, async server state, security, a TypeScript deep dive, testing, advanced plugins, scaling, v4 features, and production architecture. All of that forms one complete foundation.
That order was deliberately built in stages: concepts first, then practice, then security and quality. What was still a prerequisite in episode 0 is now used every day — ref and computed become everyday language, storeToRefs prevents reactivity bugs, plugins handle persistence, and CI gates keep quality high as the team grows.
If asked what single thing ties it all together, the answer is a way of thinking: every decision — whether to use a store or a composable, Options or Setup, Pinia or Vue Query — is made based on context and consequences. Those episodes aren't a list of tricks to memorize; they're the same mental exercise repeated at different difficulty levels. At this point you don't just know the Pinia API — you can weigh when a pattern brings value and when it becomes a burden.
To close the discussion, it's also important to recognize the limits: Pinia isn't always the best choice. State used by only one component that doesn't need to be shared is better left as a local ref — bringing it into a store only adds distance between the data and where it's used. Data that comes from the server and changes quickly — product lists, search results, feeds — is better handled by Pinia Colada or Vue Query, which provide caching, invalidation, and retry. Likewise, teams with a strict preference for architecture without global dependencies often choose more granular signal-based stores.
// single-component local state: a ref is enough
const isOpen = ref(false)
// server state: hand it to Colada or Vue Query
useProductsQuery()
// client state across components: this is Pinia's domain
useCartStore()This dividing line isn't about prohibitions, it's about priorities: use the simplest tool that satisfies the need. Pinia sits right in the middle of the spectrum — light enough for shared client state, and powerful when paired with a server-state library. Awareness of these limits actually makes Pinia used more precisely, not abandoned.
Vue keeps evolving. Vapor Mode — a runtime without Virtual DOM that uses granular updates — is on its way to stable, and the signals concept is being evaluated as a future reactivity primitive. Pinia is built on top of Vue's reactivity, so no matter what changes in the runtime, the store layer above it stays relevant.
For practitioners, this direction means two things. First, the skills you've built in this series won't go stale: defineStore, storeToRefs, and the plugin system attach to reactivity concepts that keep maturing, not to Virtual DOM details. Second, keep monitoring the Vue and Pinia changelogs — new features like a signal primitive could open up more efficient patterns for granular updates without changing how you write stores today.
Success
Congratulations on finishing the Learning Pinia series! You now have a complete foundation: concepts, patterns, security, testing, all the way to production architecture. Keep building, keep measuring, and keep learning.
Episode 22 closes this series with a clear perspective. You can now compare Pinia with its alternatives, apply the 2026 decision framework, and understand where the evolution of Vue and Pinia is heading.
Key takeaways:
The Learning Pinia journey is complete — but its application has only just begun in your projects. Use the map from this episode to make decisions with confidence.
Come back to a specific episode whenever you face a new challenge — that's the sign of a healthy series. Happy building.