PostgreSQL storage provides enterprise-grade persistence for Mastra with ACID transactions, custom indexes, and schema management.
Installation
Configuration
Connection String
Import PostgresStore
import { PostgresStore } from '@mastra/pg' ;
Create storage with connection string
const storage = new PostgresStore ({
id: 'my-storage' ,
connectionString: process . env . DATABASE_URL ! ,
});
Configure Mastra
import { Mastra } from '@mastra/core' ;
const mastra = new Mastra ({
storage ,
});
Host Configuration
const storage = new PostgresStore ({
id: 'my-storage' ,
host: 'localhost' ,
port: 5432 ,
database: 'mastra' ,
user: 'postgres' ,
password: process . env . PG_PASSWORD ! ,
});
import { Pool } from 'pg' ;
import { PostgresStore } from '@mastra/pg' ;
const pool = new Pool ({
connectionString: process . env . DATABASE_URL ! ,
max: 20 ,
idleTimeoutMillis: 30000 ,
});
const storage = new PostgresStore ({
id: 'my-storage' ,
pool ,
});
Configuration Options
Unique identifier for the storage instance
PostgreSQL connection string (e.g., postgresql://user:pass@host:5432/db)
Database host (alternative to connectionString)
SSL configuration for secure connections
PostgreSQL schema to use for tables
Maximum number of connections in the pool
Milliseconds before idle connections are closed
Skip creating default indexes on tables
Custom index configurations per domain
Disable automatic table initialization
Usage Examples
Access Storage Domains
const storage = new PostgresStore ({
id: 'storage' ,
connectionString: process . env . DATABASE_URL ! ,
});
// Access memory domain
const memory = await storage . getStore ( 'memory' );
await memory ?. saveThread ({ thread });
// Access workflows domain
const workflows = await storage . getStore ( 'workflows' );
await workflows ?. persistWorkflowSnapshot ({
workflowName: 'my-workflow' ,
runId: 'run-123' ,
snapshot ,
});
Custom Schema
const storage = new PostgresStore ({
id: 'storage' ,
connectionString: process . env . DATABASE_URL ! ,
schemaName: 'mastra_prod' ,
});
Direct Database Access
const storage = new PostgresStore ({
id: 'storage' ,
connectionString: process . env . DATABASE_URL ! ,
});
// Execute custom queries
const result = await storage . db . any (
'SELECT * FROM users WHERE active = $1' ,
[ true ]
);
// Access the underlying pg.Pool
const client = await storage . pool . connect ();
try {
await client . query ( 'BEGIN' );
// ... your queries
await client . query ( 'COMMIT' );
} finally {
client . release ();
}
Custom Indexes
const storage = new PostgresStore ({
id: 'storage' ,
connectionString: process . env . DATABASE_URL ! ,
skipDefaultIndexes: false ,
indexes: {
memory: [
{
columns: [ 'user_id' , 'created_at' ],
method: 'btree' ,
unique: false ,
},
],
workflows: [
{
columns: [ 'workflow_name' , 'status' ],
method: 'btree' ,
},
],
},
});
Schema Export
Export Mastra schema as SQL DDL for version control:
import { exportSchemas } from '@mastra/pg' ;
// Export for public schema
const ddl = exportSchemas ();
// Export for custom schema
const ddl = exportSchemas ( 'mastra_prod' );
// Write to file
import { writeFileSync } from 'fs' ;
writeFileSync ( 'schema.sql' , ddl );
Storage Domains
PostgreSQL storage supports all Mastra domains:
memory - Thread-based conversation persistence
workflows - Workflow execution snapshots
observability - Telemetry and logging
agents - Agent configurations
datasets - Training and evaluation datasets
experiments - Evaluation experiment results
promptBlocks - Reusable prompt templates
scorerDefinitions - Evaluation scorer configurations
mcpClients - MCP client configurations
mcpServers - MCP server configurations
workspaces - Workspace metadata
skills - Agent skill definitions
blobs - Binary large object storage
Connection Pooling
const storage = new PostgresStore ({
id: 'storage' ,
connectionString: process . env . DATABASE_URL ! ,
max: 50 , // Increase pool size for high concurrency
idleTimeoutMillis: 60000 , // Keep connections alive longer
});
Custom Indexes for Queries
const storage = new PostgresStore ({
id: 'storage' ,
connectionString: process . env . DATABASE_URL ! ,
indexes: {
observability: [
{
columns: [ 'trace_id' , 'timestamp' ],
method: 'btree' ,
},
{
columns: [ 'span_name' ],
method: 'hash' ,
},
],
},
});
SSL Configuration
Basic SSL
const storage = new PostgresStore ({
id: 'storage' ,
connectionString: process . env . DATABASE_URL ! ,
ssl: true ,
});
Custom SSL
import { readFileSync } from 'fs' ;
const storage = new PostgresStore ({
id: 'storage' ,
connectionString: process . env . DATABASE_URL ! ,
ssl: {
rejectUnauthorized: true ,
ca: readFileSync ( './ca-certificate.crt' ). toString (),
},
});
Vector Store Support
PostgreSQL also provides pgvector support:
import { PgVector } from '@mastra/pg' ;
const vectorStore = new PgVector ({
id: 'vectors' ,
connectionString: process . env . DATABASE_URL ! ,
});
const mastra = new Mastra ({
vectors: {
embeddings: vectorStore ,
},
});
See pgvector documentation for more details.
Best Practices
Use Connection Pooling Let PostgresStore manage the connection pool for optimal performance.
Schema Isolation Use custom schemas in multi-tenant deployments: schemaName : `tenant_ ${ tenantId } `
Index Strategy Profile queries and add custom indexes for frequently filtered columns.
Connection Limits Set appropriate pool sizes based on your workload:
API servers: 20-50 connections
Background workers: 5-10 connections
Cleanup
Close connections when shutting down:
const storage = new PostgresStore ({
id: 'storage' ,
connectionString: process . env . DATABASE_URL ! ,
});
// ... use storage
// Clean up
await storage . close ();
pgvector PostgreSQL vector extension for embeddings
LibSQL Storage Lightweight SQLite-compatible storage
PostgreSQL Docs Official PostgreSQL documentation
node-postgres PostgreSQL client for Node.js