docs/src/content/en/reference/storage/convex.mdx
The Convex storage implementation provides a serverless storage solution using Convex, a full-stack TypeScript development platform with real-time sync and automatic caching.
:::warning[Observability Not Supported]
Convex storage doesn't support the observability domain. Traces from the DefaultExporter can't be persisted to Convex, and Mastra Studio's observability features won't work with Convex as your only storage provider. To enable observability, use composite storage to route observability data to a supported provider like ClickHouse or PostgreSQL.
:::
:::warning[Record Size Limit] Convex enforces a 1 MiB maximum record size. This limit can be exceeded when storing messages with base64-encoded attachments such as images. See Handling large attachments for workarounds including uploading attachments to external storage like S3, Cloudflare R2, or Convex file storage. :::
npm install @mastra/convex@latest
Before using ConvexStore, you need to set up the Convex schema and storage handler in your Convex project.
In convex/schema.ts:
import { defineSchema } from 'convex/server'
import {
mastraThreadsTable,
mastraMessagesTable,
mastraResourcesTable,
mastraWorkflowSnapshotsTable,
mastraScoresTable,
mastraVectorIndexesTable,
mastraVectorsTable,
mastraDocumentsTable,
} from '@mastra/convex/schema'
export default defineSchema({
mastra_threads: mastraThreadsTable,
mastra_messages: mastraMessagesTable,
mastra_resources: mastraResourcesTable,
mastra_workflow_snapshots: mastraWorkflowSnapshotsTable,
mastra_scorers: mastraScoresTable,
mastra_vector_indexes: mastraVectorIndexesTable,
mastra_vectors: mastraVectorsTable,
mastra_documents: mastraDocumentsTable,
})
In convex/mastra/storage.ts:
import { mastraStorage } from '@mastra/convex/server'
export const handle = mastraStorage
npx convex dev
# or for production
npx convex deploy
import { ConvexStore } from '@mastra/convex'
const storage = new ConvexStore({
id: 'convex-storage',
deploymentUrl: process.env.CONVEX_URL!,
adminAuthToken: process.env.CONVEX_ADMIN_KEY!,
})
<PropertiesTable content={[ { name: 'deploymentUrl', type: 'string', description: 'Convex deployment URL (e.g., https://your-project.convex.cloud)', isOptional: false, }, { name: 'adminAuthToken', type: 'string', description: 'Convex admin authentication token for backend access', isOptional: false, }, { name: 'storageFunction', type: 'string', description: "Path to the storage mutation function (default: 'mastra/storage:handle')", isOptional: true, defaultValue: 'mastra/storage:handle', }, ]} />
import { ConvexStore } from '@mastra/convex'
// Basic configuration
const store = new ConvexStore({
id: 'convex-storage',
deploymentUrl: 'https://your-project.convex.cloud',
adminAuthToken: 'your-admin-token',
})
// With custom storage function path
const storeCustom = new ConvexStore({
id: 'convex-storage',
deploymentUrl: 'https://your-project.convex.cloud',
adminAuthToken: 'your-admin-token',
storageFunction: 'custom/path:handler',
})
The storage implementation uses typed Convex tables for each Mastra domain:
| Domain | Convex Table | Purpose |
|---|---|---|
| Threads | mastra_threads | Conversation threads |
| Messages | mastra_messages | Chat messages |
| Resources | mastra_resources | User working memory |
| Workflows | mastra_workflow_snapshots | Workflow state |
| Scorers | mastra_scorers | Evaluation data |
| Fallback | mastra_documents | Unknown tables |
All typed tables include:
id field for Mastra's record ID (distinct from Convex's auto-generated _id)by_record_id index for efficient lookups by Mastra IDThis design ensures compatibility with Mastra's storage contract while leveraging Convex's automatic indexing and real-time capabilities.
Set these environment variables for your deployment:
CONVEX_URL – Your Convex deployment URLCONVEX_ADMIN_KEY – Admin authentication token (get from Convex dashboard)