Why query-tags?
Your mutations shouldn't know about your queries
Manual cache invalidation is the hidden coupling tax you pay on every feature. Here's why it hurts, and how tag-based invalidation fixes it for good.
The Problem
Every mutation knows about every query
As your app grows, each mutation accumulates a list of query keys it must invalidate. Add a new query? Update every mutation that might affect it. It's hidden coupling, and it compounds.
// In your "createTodo" mutation handler
const addTodo = useMutation({
mutationFn: createTodo,
onSuccess: () => {
// You need to remember EVERY query that touches todos
queryClient.invalidateQueries({ queryKey: ['todos'] })
queryClient.invalidateQueries({ queryKey: ['todos', 'count'] })
queryClient.invalidateQueries({ queryKey: ['todos', 'recent'] })
queryClient.invalidateQueries({ queryKey: ['stats'] })
queryClient.invalidateQueries({ queryKey: ['dashboard'] })
// Did I get all of them? What about the other tab?
// What about the route loader? New teammate added a query — now out of sync.
}
})// On the server, once, in your action handler
await tagInvalidation.invalidateTags({
tags: [appTags.todos()]
})
// That's it. Every query tagged with "todos.*" updates.
// Every tab. Every loader. Every component. Automatically.
// New query added? Just tag it — zero mutation changes needed.Mutation drift
New queries are added but mutations aren't updated. Stale data silently appears.
Cross-tab blindness
queryClient.invalidateQueries() only affects the current browser tab.
Loader amnesia
Route loaders re-run on navigation, not on data mutation — missed refetches everywhere.
Comparison
query-tags vs alternatives
How does it stack up against rolling your own or using Next.js revalidateTag?
| Feature | Manual | Next.js revalidateTag | query-tags |
|---|---|---|---|
| Type-safe tag references | ✕ | ✕ | ✓ |
| Multi-tab sync | ✕ | ✕ | ✓ |
| Hierarchical invalidation | ✕ | ✕ | ✓ |
| Per-tenant scoping | ✕ | ✕ | ✓ |
| Route loader refresh | ✕ | ✓ | ✓ |
| Works with TanStack Query | ✓ | ✕ | ✓ |
| No framework lock-in | ✓ | ✕ | ~ |
| Debug tooling | ~ | ✕ | ✓ |
Ready?
Get started in 5 minutes
Follow the step-by-step guide to add query-tags to your TanStack Start app.
Read the guide →