Unexpected query invalidation behavior — mutation waits for refetches across unrelated queries
Hi Convex team,
I built a minimal reproduction and wanted to report the unexpected behavior I observed when calling a mutation that inserts a new message.
Short summary
- Mutation (DB write) completes quickly on the server (~0-30ms).
- The client-side mutation promise does not resolve immediately — it waits while multiple queries refetch.
- Convex revalidates all queries that touch the
messages
table (including a global getAllMessages
query and per-period queries), even when the mutation’s data clearly only belongs to one query (e.g. "after cutoff").
- This causes the mutation to appear to take the combined refetch time on the frontend (in my test ~765ms), even though the backend mutation duration is ~0ms.
Reproduction steps (repo included)
1. Clone the public test repo: https://github.com/williamneves/convex-lab
2. Run Convex dev: npx convex dev
3. Start the frontend (Bun/Next): bun run dev
and open the UI.
4. Click “Seed Users” and “Seed 20 Messages”.
5. Set a cutoff date and click “Generate Before Message” or “Generate After Message”.
6. Watch the Timing Analysis card and Convex logs.
Observed logs (snippet)
- insertMessage logs (server):
— Convex shows the mutation finished in ~0–26ms in the server logs.
- Queries revalidation logs (server):
- Frontend timing (UI card): Backend Mutation: 0ms
, DB Op: 0ms
, Frontend Total: 765ms
— frontend waited ~765ms for mutation promise to resolve.
Observed behavior summary
- The mutation completes on the server almost instantly.
- The client-side mutation promise resolves only after all related queries have re-fetched (including ones whose args should not match the new message).
- getAllMessages
is refetched even when the mutation only affects the “after” list — this results in unnecessary refetches and the user-perceived latency of the mutation includes query refetch time.
Expected behavior
- Mutation resolution should reflect the mutation’s server-side work (DB write + any server work).
- Query invalidation/refetch should be triggered but should not block the mutation promise resolution unless explicitly configured to do so.
- Ideally, invalidations should be scoped: only queries whose arguments indicate they could be affected by the mutation should be revalidated.
Questions / requests
1. Is the Convex client intended to wait for query revalidations before resolving a mutation promise? If so, is this configurable (non-blocking refetch vs. blocking)?
2. Is there a way to scope invalidation so only queries with matching args are revalidated (so getAllMessages
would not refetch if I inserted a message that only matched after
)?
3. If current behavior is intentional, can you document when mutations block on refetches, and whether there’s a way to change that behavior (e.g., optimistic updates, fire-and-forget revalidation)?
4. I can provide the small test repo link, console logs, and server logs; what additional info would be most helpful for triage?
Repository & logs
- Repo: https://github.com/williamneves/convex-lab
- I can attach full terminal logs and Convex function logs if useful.GitHub
GitHub - williamneves/convex-lab
Contribute to williamneves/convex-lab development by creating an account on GitHub.


0 Replies