Skip to main content

Query Ownership and Caching

Understand where query results live and when to share state instead of copying it.

“Cache” can refer to several different owners in one Nuxt page. Distinguishing them prevents duplicate state.

Where state lives

StateOwnerLifetime
Convex query result and wire deduplicationCurrent Convex clientClient lifetime and identity generation
SSR resultNuxt payload/async dataRequest and hydrated payload
data, error, status, transformComposable instanceVue effect scope
Shared Vue query stateOne defineSharedConvexQuery closureNuxt app instance
Optimistic overlayConvex client plus helper updateUntil server confirmation or rollback
UI-only stateComponent or application storeApplication-defined

There is no separate Better Convex Nuxt entity cache.

Identical subscriptions

Two mounted components may request the same Convex query and arguments. Convex owns wire-level subscription deduplication. The module does not maintain a parallel subscription registry.

Each composable still has its own Vue-visible state. That is useful when components apply different transforms or loading presentation.

Share Vue state deliberately

Use defineSharedConvexQuery when multiple components must consume the same transformed state and lifecycle:

ts
// app/composables/useCurrentTeam.ts
import { api } from '#convex/api'

export const useCurrentTeam = defineSharedConvexQuery({
  key: 'current-team',
  query: api.teams.current,
  args: {},
  options: { auth: 'required' },
})
ts
const { data: team, status } = useCurrentTeam()

The returned closure is the definition identity. It creates one shared state per Nuxt app. The string key is for diagnostics; it is not a global registry key.

Reactive argument identity

A query is identified by its function reference, normalized arguments, auth boundary, and current identity generation. Changing arguments creates a new requested result.

keepPreviousData: true may retain the previous result while new arguments load. It never carries data across an identity boundary.

Convex data versus Pinia

Keep server-backed entities in Convex queries. Use Pinia or local refs for UI state such as:

  • open panels and dialogs;
  • unsaved local drafts;
  • wizard progress;
  • client preferences that are not server data.

Copying query entities into Pinia creates synchronization work: refresh, optimistic rollback, sign-out clearing, and live update reconciliation all gain a second implementation.

No cross-request cache promise

A shared query definition does not cache results between SSR requests. Each server request has its own Nuxt app and identity context.

If a deployment adds HTTP or page caching, its privacy and invalidation rules belong to that deployment layer. Read performance before caching authenticated pages.