Convex Storage
The Convex storage implementation provides a serverless storage solution using Convex, a full-stack TypeScript development platform with real-time sync and automatic caching.
Convex storage does not support the observability domain. Traces from the DefaultExporter cannot 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.
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.
InstallationDirect link to Installation
- npm
- pnpm
- Yarn
- Bun
npm install @mastra/convex@latest
pnpm add @mastra/convex@latest
yarn add @mastra/convex@latest
bun add @mastra/convex@latest
Convex SetupDirect link to Convex Setup
Before using ConvexStore, you need to set up the Convex schema and storage handler in your Convex project.
1. Set up Convex SchemaDirect link to 1. Set up Convex Schema
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,
});
2. Create the Storage HandlerDirect link to 2. Create the Storage Handler
In convex/mastra/storage.ts:
import { mastraStorage } from '@mastra/convex/server';
export const handle = mastraStorage;
3. Deploy to ConvexDirect link to 3. Deploy to Convex
npx convex dev
# or for production
npx convex deploy
UsageDirect link to Usage
import { ConvexStore } from "@mastra/convex";
const storage = new ConvexStore({
id: 'convex-storage',
deploymentUrl: process.env.CONVEX_URL!,
adminAuthToken: process.env.CONVEX_ADMIN_KEY!,
});
ParametersDirect link to Parameters
deploymentUrl:
adminAuthToken:
storageFunction?:
Constructor ExamplesDirect link to Constructor Examples
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",
});
Additional NotesDirect link to Additional Notes
Schema ManagementDirect link to Schema Management
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 |
ArchitectureDirect link to Architecture
All typed tables include:
- An
idfield for Mastra's record ID (distinct from Convex's auto-generated_id) - A
by_record_idindex for efficient lookups by Mastra ID
This design ensures compatibility with Mastra's storage contract while leveraging Convex's automatic indexing and real-time capabilities.
Environment VariablesDirect link to Environment Variables
Set these environment variables for your deployment:
CONVEX_URL– Your Convex deployment URLCONVEX_ADMIN_KEY– Admin authentication token (get from Convex dashboard)