The Plugin Data Model
A plugin owns its data. The core provides the workspace and workflow_execution tables; your plugin provides everything domain-specific — and clips onto the core through a small, disciplined set of tables. This is that data model. (The Default Plugin ER Diagram shows it visually.)
The two required tables
Entity object table — named after your entity (e.g. default_plugin_thing). It holds your domain fields, and optionally entity-level pointers like active_workspace_id and final_workspace_id (both FKs to core workspace, nullable). Not every plugin needs those pointers.
Join table — named {entity_slug}_workspace, linking your entity to core workspaces. It has required columns:
{entity_slug}_id— FK to your entity object;workspace_id— FK to coreworkspace;is_deletedandis_archived— plugin-owned booleans.
A unique constraint on (entity_id, workspace_id) keeps the link clean. Your queries must filter on is_deleted / is_archived to hide deleted/archived workspaces — because core workspaces are never actually deleted, deletion and archival are your soft-flags on this table.
Domain tables
Beyond the two required tables, add whatever your domain needs. The default plugin adds default_plugin_section (grouping), default_plugin_output (workflow results, with an output_type and a nullable workflow_execution_id), and default_plugin_input (append-only operator input), plus helper views. Reference core tables via FKs where useful — but never the other direction.
The invariant that governs it all
Every foreign key points from a plugin table to a core table (or to another plugin table) — never from a core table to a plugin table. The core is unaware of your plugin's shape. This one-way rule is what keeps the boundary clean: you can build any data model you like, as long as the arrows only point inward.
Naming conventions
- Prefix every plugin table with your entity slug (avoids collisions; plugin tables share the
circusschema with core). - Singular nouns (
default_plugin_thing, not_things); snake_case; FK columns as{referenced_table}_id.
Where the schema lives
Your tables are defined by your migrations (plugins/{entity_slug}/migrations/), which are the authoritative schema for your plugin — see Writing Plugin Migrations. The default plugin's migrations are the maintained reference to study.