Skip to main content

Performance

Remove unnecessary query stages, reduce payloads, and measure the Nuxt-to-Convex lifecycle.

Optimize the lifecycle you actually use. Do not add another cache before identifying the expensive stage.

  1. Measure SSR, navigation, payload size, and subscription activity.
  2. Disable a lifecycle stage the page does not need.
  3. Return less data and paginate growing collections.
  4. Avoid unnecessary auth work on public paths.
  5. Tune deployment and auth verification from evidence.

Remove unnecessary SSR

Use server: false for browser-specific data that does not improve the initial HTML.

ts
await useConvexQuery(api.presence.current, {}, { server: false })

The cost is a browser loading state and no server-rendered value.

Remove unnecessary subscriptions

Use subscribe: false for stable snapshots and reports:

ts
await useConvexQuery(api.reports.monthly, args, { subscribe: false })

The result will not change until refresh() or navigation runs it again.

Keep public data independent of auth

auth: 'none' skips auth settlement and always uses anonymous transport. Use it only for functions whose result and authorization are truly identity-independent.

Bound result size

Return fields the page uses. Use indexes and take() for bounded lists. Use pagination for growing collections. Large SSR results increase Convex work, HTML/payload size, parsing, and hydration cost.

Understand duplicate dashboard calls

The default SSR-to-live lifecycle creates one server HTTP query and one browser subscription. This is not a duplicate subscription bug. Disable a stage only when its product benefit is unnecessary.

Avoid a mirrored store

Copying Convex entities into Pinia adds update and identity-clearing work. Use normal or shared queries and keep stores for UI-only state.

Measure production behavior

Development includes HMR, DevTools, source maps, and extra diagnostics. Use production builds and representative deployment regions before drawing latency conclusions.