Skip to main content
This guide shows plugin developers how to add database tables to their elizaOS plugins. The plugin-sql system automatically handles schema creation, migrations, and namespacing.

Overview

Any elizaOS plugin can define its own database tables by:
  1. Creating table definitions using Drizzle ORM
  2. Exporting a schema property from the plugin
  3. That’s it! Tables are created automatically on startup

Step-by-Step Guide

1. Set Up Your Plugin Structure

2. Define Your Tables

Create table definitions using Drizzle ORM:

3. Create Schema Index

Export all your tables from a central location:

4. Export Schema from Plugin

The critical step - export your schema from the plugin:

Schema Namespacing

Your plugin’s tables are automatically created in a dedicated PostgreSQL schema:
This prevents naming conflicts between plugins.

Working with Foreign Keys

Reference Core Tables

To reference tables from the core plugin:

Reference Your Own Tables

For relationships within your plugin:

Cross-Plugin References

To reference tables from other plugins:

Table Design Patterns

User Tables

Event/Log Tables

Configuration Tables

Advanced Features

Composite Primary Keys

Check Constraints

Generated Columns

Querying Your Tables

Once your tables are created, you can query them using Drizzle:

Best Practices

1. Prefix Table Names

Use a consistent prefix for your plugin’s tables:

2. Always Include Timestamps

3. Use JSONB Wisely

JSONB is great for flexibility but don’t overuse it:

4. Index Foreign Keys

Always index columns used in joins:

5. Handle Cascading Deletes

Be explicit about deletion behavior:

Troubleshooting

Tables Not Created

  1. Ensure your plugin exports the schema:
  2. Check the logs for migration errors:
  3. Verify table names don’t conflict with PostgreSQL keywords

Foreign Key Errors

  1. Ensure referenced tables exist
  2. Check that data types match exactly
  3. Verify the referenced column has a unique constraint

Performance Issues

  1. Add indexes for frequently queried columns
  2. Use partial indexes for filtered queries
  3. Consider partitioning for large tables