Overview
elizaOS uses Drizzle ORM with PostgreSQL/PGLite and features a powerful dynamic migration system that automatically manages database schema changes at runtime. This guide demonstrates how to add custom tables to your plugins, create repositories for data access, and build actions and providers to interact with your data.Key Features
- Automatic Migrations: Schema changes are detected and applied automatically
- PGLite & PostgreSQL Support: Works with both databases seamlessly
- Schema Isolation: Each plugin gets its own namespace to avoid conflicts
- Safety First: Destructive changes are blocked in production by default
- Zero Configuration: No manual migration files needed
Important: Drizzle ORM version in your plugin must match the monorepo version. Check packages/core/package.json for the exact version required.
Dynamic Migration System
Since ElizaOS 1.0, plugins can define schemas that are automatically migrated without any manual intervention. The system:- Detects Changes: Compares your schema with the database state
- Generates SQL: Creates migration statements automatically
- Applies Safely: Runs migrations in transactions with rollback capability
- Tracks History: Maintains complete audit trail of all schema changes
Database Compatibility
| Database | Development | Production | Features | |------------|-------------|------------|-----------------------------------|| | PGLite | ✅ Recommended | ⚠️ Limited | Fast, in-memory, no setup needed | | PostgreSQL | ✅ Supported | ✅ Recommended | Full features, vector search, scaling |Version Requirements
Critical: Your plugin’s Drizzle version must match the monorepo version:Step 1: Define Your Custom Schema
Schema Namespacing
Important: Plugins should use namespaced schemas to avoid conflicts:- Core Plugin (
@elizaos/plugin-sql): Uses thepublicschema - All Other Plugins: Must use
plugin_<name>schema namespace
Creating a Shared Table
To create a table accessible by all agents (noagentId field):
- Use
pgSchema('plugin_yourname')for namespace isolation - Tables without
agentIdare shared across all agents - Migrations are generated and applied automatically at runtime
- Indexes are created automatically with the table
Creating Agent-Specific Tables
For data that should be scoped to individual agents:PGLite Compatibility Notes
Step 2: Create a Repository for Database Access
Repository Pattern
Create a repository class to handle database operations. This follows the pattern used throughout elizaOS:Advanced Repository Patterns
Transactions
Complex Queries
Step 3: Create an Action to Write Data
Action Structure
Actions process user input and store data using the repository:Batch Operations Action
Step 4: Create a Provider to Read Data
Provider Structure
Providers make data available to agents during conversations:Caching Provider
Step 5: Register Your Components
Plugin Configuration
Register your schema with your plugin - migrations run automatically:How Migrations Run
When your plugin loads:- Schema Discovery: System finds your schema definition
- Diff Generation: Compares with current database state
- Safety Check: Blocks destructive changes in production
- Migration: Applies changes in a transaction
- Recording: Stores migration history in
migrationsschema
Important Considerations
1. Drizzle Version Matching
Critical: Your plugin must use the same Drizzle ORM version as the monorepo:- Migration generation failures
- Type incompatibilities
- Runtime errors
- Schema sync issues
2. Schema Namespacing & Data Patterns
agentId in your tables:
- All agents can read and write the same data
- Use
userIdor other identifiers to scope data appropriately - Consider data consistency across multiple agents
3. Database Compatibility
| Feature | PGLite | PostgreSQL | Notes |
|---|---|---|---|
| Basic Tables | ✅ | ✅ | Full support |
| Indexes | ✅ | ✅ | Full support |
| JSON/JSONB | ✅ | ✅ | Full support |
| Vectors | ⚠️ | ✅ | PGLite has dimension limits |
| Extensions | ❌ | ✅ | PGLite doesn’t support all |
| Advisory Locks | ❌ | ✅ | PGLite skips locking |
4. Error Handling
5. Migration Behavior
- Adding new tables
- Adding nullable columns
- Adding indexes
- Extending varchar length
- Dropping tables or columns
- Changing column types
- Adding NOT NULL to existing columns
Complete Example Workflow
1. Initial Setup
2. Define Your Schema
3. Register with Plugin
4. Runtime Flow
- Plugin Loads: Schema detected, migrations run automatically
- User Message: “I prefer dark theme and Spanish language”
- Action Executes: Stores preferences in database
- Provider Reads: Supplies preferences to agent context
- Multiple Agents: All agents access the same schema namespace
Advanced Patterns
Embeddings and Vector Search
Time-Series Data
Troubleshooting Common Issues
”Drizzle version mismatch” Error
”Schema already exists” in PGLite
”Destructive migration blocked” in Production
”Cannot find module ‘drizzle-orm/pg-core‘“
Migration Not Running
Summary
To add custom schema to an elizaOS plugin with automatic migrations:- Match Drizzle Version: Use the same version as the monorepo (
bun add drizzle-orm@^0.36.0) - Use Schema Namespacing: Always use
pgSchema('plugin_yourname')for isolation - Define Your Tables: Create tables with or without
agentIdfor scoping - Register Schema: Add schema to plugin definition for automatic migrations
- Build Components: Create repositories, actions, and providers
- Let Migrations Run: System handles everything automatically on startup

