Skip to main content

Limitations and trade-offs

Know the costs and unsupported cases before you adopt the module.

The module makes fixed choices so that SSR, live data, and auth work together. These choices have costs.

A server-rendered live query runs twice

By default, a query runs:

  1. Once over HTTP during server rendering.
  2. Once as a WebSocket subscription in the browser.

The first run produces the HTML. The second keeps the data live. The Convex dashboard shows both runs.

Turn off server rendering for data that only the browser needs:

ts
useConvexQuery(api.notifications.list, {}, { server: false })

Every useConvexQuery subscribes in the browser. For a one-time read, call useConvex().query(...) or serverConvex in a Nuxt server route.

Nuxt auth uses Better Auth

The Nuxt module supports Better Auth only. Another auth provider needs your own integration.

The plain Vue package accepts any provider through an auth adapter. See plain Vue and Vite.

Omit convex.auth when the app has no sign-in. The build then contains no auth plugins, proxy, middleware, or Better Auth code. Use auth: false only to remove auth that a Nuxt layer added.

You write the permission checks

The module knows who the user is. It does not know whether that user may edit a project or read a document.

Check permissions inside Convex functions. Route middleware and hidden buttons only change the UI.

Some Better Auth plugins need extra setup

The module supports the organization, two-factor, and email OTP plugins, and the OAuth provider plugin for MCP. It rejects every other Better Auth plugin, for example admin and API keys. See Better Auth plugin support.

The organization and two-factor plugins change the auth database schema. They need a matching server option, a regenerated schema, and a typed client. Run better-convex auth schema to regenerate the schema. See Better Auth plugins.

The raw Convex client is not available

useConvex() returns only query, mutation, action, and onUpdate. It does not return setAuth, clearAuth, connectionState, or close.

The module replaces the client when the user changes. A kept reference to an old client would break. Use useConvexConnectionState() to read the connection state.

Query data belongs to the component

Each query composable keeps its own data for the component that created it. There is no shared cache across requests or users.

Convex is the source of truth for server data. Use Pinia or local state only for UI state, not for copies of Convex documents.

Better Auth versions are pinned

better-auth, @better-auth/core, and @better-auth/oauth-provider must be exactly 1.7.6. Nuxt and Convex accept a range. Upgrade Better Auth only together with a new version of this module.

Auth needs a new database

The auth component does not import users from another auth setup. Start with an empty component database, registered as betterAuth.

OAuth for MCP supports one setup

The OAuth provider for MCP hosts supports:

  • preregistered clients, both confidential and public;
  • authorization code with PKCE S256 and explicit consent;
  • one resource per token and short-lived access tokens;
  • refresh tokens tied to the session that gave consent.

It does not support dynamic client registration, client credentials, DPoP, or tokens for several resources. See delegated OAuth and MCP.

Read release compatibility before you override any version.