Overview
Shannon uses PostgreSQL with pgvector extension for persistent storage. The database is organized into two schemas:- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
Entity Relationship Diagram
Schema: auth (Authentication & Multi-Tenancy)
auth.tenants
Purpose: Multi-tenant organization management| Column | Type | Constraints | Description |
|---|---|---|---|
| id | UUID | PK, DEFAULT gen_random_uuid() | Tenant identifier |
| name | VARCHAR(255) | NOT NULL | Organization name |
| slug | VARCHAR(100) | UNIQUE, NOT NULL | URL-safe identifier |
| plan | VARCHAR(50) | DEFAULT ‘free’ | Subscription plan (free, pro, enterprise) |
| token_limit | INTEGER | DEFAULT 10000 | Monthly token allowance |
| monthly_token_usage | INTEGER | DEFAULT 0 | Current month usage |
| rate_limit_per_hour | INTEGER | DEFAULT 1000 | API rate limit |
| is_active | BOOLEAN | DEFAULT true | Tenant status |
| created_at | TIMESTAMP | DEFAULT NOW() | Creation time |
| updated_at | TIMESTAMP | DEFAULT NOW() | Last update time |
| metadata | JSONB | DEFAULT '' | Additional tenant data |
idx_sessions_user_idON (user_id)idx_sessions_tenant_idON (tenant_id)idx_sessions_expires_atON (expires_at)idx_sessions_external_idON ((context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULLidx_sessions_user_external_idUNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULLidx_sessions_not_deletedON (id) WHERE deleted_at IS NULL
auth.users
Purpose: User authentication and profile management| Column | Type | Constraints | Description |
|---|---|---|---|
| id | UUID | PK, DEFAULT gen_random_uuid() | User identifier |
| VARCHAR(255) | UNIQUE, NOT NULL | User email | |
| username | VARCHAR(100) | UNIQUE, NOT NULL | Username |
| password_hash | VARCHAR(255) | NOT NULL | Bcrypt password hash |
| full_name | VARCHAR(255) | Full name | |
| tenant_id | UUID | FK → auth.tenants, NOT NULL | Organization |
| role | VARCHAR(50) | DEFAULT ‘user’ | Role (user, admin, owner) |
| is_active | BOOLEAN | DEFAULT true | Account status |
| is_verified | BOOLEAN | DEFAULT false | Email verification |
| email_verified_at | TIMESTAMP | Verification timestamp | |
| created_at | TIMESTAMP | DEFAULT NOW() | Account creation |
| updated_at | TIMESTAMP | DEFAULT NOW() | Last update |
| last_login | TIMESTAMP | Last login time | |
| metadata | JSONB | DEFAULT '' | Additional user data |
idx_sessions_user_idON (user_id)idx_sessions_tenant_idON (tenant_id)idx_sessions_expires_atON (expires_at)idx_sessions_external_idON ((context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULLidx_sessions_user_external_idUNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULLidx_sessions_not_deletedON (id) WHERE deleted_at IS NULL
auth.api_keys
Purpose: API key management for programmatic access| Column | Type | Constraints | Description |
|---|---|---|---|
| id | UUID | PK, DEFAULT gen_random_uuid() | Key identifier |
| key_hash | VARCHAR(255) | UNIQUE, NOT NULL | SHA256 hash of key |
| key_prefix | VARCHAR(20) | NOT NULL | First 8 chars (for display) |
| user_id | UUID | FK → auth.users | Key owner |
| tenant_id | UUID | FK → auth.tenants, NOT NULL | Organization |
| name | VARCHAR(100) | NOT NULL | Key name/description |
| description | TEXT | Detailed description | |
| scopes | TEXT[] | DEFAULT […] | Permissions array |
| rate_limit_per_hour | INTEGER | DEFAULT 1000 | Key-specific rate limit |
| last_used | TIMESTAMP | Last usage timestamp | |
| expires_at | TIMESTAMP | Expiration time | |
| is_active | BOOLEAN | DEFAULT true | Key status |
| created_at | TIMESTAMP | DEFAULT NOW() | Creation time |
| metadata | JSONB | DEFAULT '' | Additional key data |
idx_sessions_user_idON (user_id)idx_sessions_tenant_idON (tenant_id)idx_sessions_expires_atON (expires_at)idx_sessions_external_idON ((context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULLidx_sessions_user_external_idUNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULLidx_sessions_not_deletedON (id) WHERE deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
auth.refresh_tokens
Purpose: JWT refresh token storage and revocation| Column | Type | Constraints | Description |
|---|---|---|---|
| id | UUID | PK, DEFAULT gen_random_uuid() | Token identifier |
| token_hash | VARCHAR(255) | UNIQUE, NOT NULL | SHA256 hash |
| user_id | UUID | FK → auth.users | Token owner |
| tenant_id | UUID | FK → auth.tenants, NOT NULL | Organization |
| expires_at | TIMESTAMP | NOT NULL | Expiration time |
| revoked | BOOLEAN | DEFAULT false | Revocation status |
| revoked_at | TIMESTAMP | Revocation time | |
| ip_address | INET | Client IP | |
| user_agent | TEXT | Client user agent | |
| created_at | TIMESTAMP | DEFAULT NOW() | Creation time |
idx_sessions_user_idON (user_id)idx_sessions_tenant_idON (tenant_id)idx_sessions_expires_atON (expires_at)idx_sessions_external_idON ((context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULLidx_sessions_user_external_idUNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULLidx_sessions_not_deletedON (id) WHERE deleted_at IS NULL
auth.audit_logs
Purpose: Security event audit trail| Column | Type | Constraints | Description |
|---|---|---|---|
| id | UUID | PK, DEFAULT gen_random_uuid() | Log entry ID |
| event_type | VARCHAR(100) | NOT NULL | Event type |
| user_id | UUID | FK → auth.users | User (nullable) |
| tenant_id | UUID | FK → auth.tenants | Tenant (nullable) |
| ip_address | INET | Client IP | |
| user_agent | TEXT | Client user agent | |
| details | JSONB | DEFAULT '' | Event details |
| created_at | TIMESTAMP | DEFAULT NOW() | Event time |
idx_sessions_user_idON (user_id)idx_sessions_tenant_idON (tenant_id)idx_sessions_expires_atON (expires_at)idx_sessions_external_idON ((context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULLidx_sessions_user_external_idUNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULLidx_sessions_not_deletedON (id) WHERE deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
Schema: public (Core Application)
users
Purpose: Application user profiles (legacy, linked to auth.users)| Column | Type | Constraints | Description |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | User identifier |
| external_id | VARCHAR(255) | UNIQUE, NOT NULL | External system ID |
| VARCHAR(255) | Email address | ||
| tenant_id | UUID | Tenant reference | |
| metadata | JSONB | DEFAULT '' | User metadata |
| created_at | TIMESTAMPTZ | DEFAULT NOW() | Creation time |
| updated_at | TIMESTAMPTZ | DEFAULT NOW() | Last update |
idx_users_tenant_idON (tenant_id)idx_users_external_idON (external_id)
auth.users.
sessions
Purpose: User session management and context| Column | Type | Constraints | Description |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | Session identifier |
| user_id | UUID | FK → users | Session owner |
| tenant_id | UUID | Tenant reference | |
| context | JSONB | DEFAULT '' | Session context data |
| token_budget | INTEGER | DEFAULT 10000 | Token allocation |
| tokens_used | INTEGER | DEFAULT 0 | Tokens consumed |
| created_at | TIMESTAMPTZ | DEFAULT NOW() | Session start |
| updated_at | TIMESTAMPTZ | DEFAULT NOW() | Last activity |
| expires_at | TIMESTAMPTZ | Expiration time |
idx_sessions_user_idON (user_id)idx_sessions_tenant_idON (tenant_id)idx_sessions_expires_atON (expires_at)idx_sessions_external_idON ((context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULLidx_sessions_user_external_idUNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULLidx_sessions_not_deletedON (id) WHERE deleted_at IS NULL
context->>'external_id' to enable dual-ID lookups.
Example:
task_executions
Purpose: Task/workflow execution history and metrics| Column | Type | Constraints | Description |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | Task identifier |
| workflow_id | VARCHAR(255) | UNIQUE, NOT NULL | Temporal workflow ID |
| user_id | UUID | FK → users | Task creator |
| tenant_id | UUID | Tenant reference | |
| session_id | VARCHAR(255) | Session identifier | |
| query | TEXT | NOT NULL | Task query/prompt |
| mode | VARCHAR(50) | Execution mode (SIMPLE, STANDARD, COMPLEX) | |
| status | VARCHAR(50) | NOT NULL | Task status |
| started_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | Start time |
| completed_at | TIMESTAMPTZ | Completion time | |
| result | TEXT | Final result | |
| response | JSONB | DEFAULT '' | Structured response |
| error_message | TEXT | Error details | |
| total_tokens | INTEGER | DEFAULT 0 | Total tokens used |
| prompt_tokens | INTEGER | DEFAULT 0 | Input tokens |
| completion_tokens | INTEGER | DEFAULT 0 | Output tokens |
| total_cost_usd | DECIMAL(10,6) | DEFAULT 0 | Total cost |
| duration_ms | INTEGER | Execution time (ms) | |
| agents_used | INTEGER | DEFAULT 0 | Number of agents |
| tools_invoked | INTEGER | DEFAULT 0 | Number of tool calls |
| cache_hits | INTEGER | DEFAULT 0 | Cache hit count |
| complexity_score | DECIMAL(3,2) | Complexity (0.0-1.0) | |
| metadata | JSONB | Additional metadata | |
| created_at | TIMESTAMPTZ | DEFAULT NOW() | Record creation |
idx_sessions_user_idON (user_id)idx_sessions_tenant_idON (tenant_id)idx_sessions_expires_atON (expires_at)idx_sessions_external_idON ((context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULLidx_sessions_user_external_idUNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULLidx_sessions_not_deletedON (id) WHERE deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
agent_executions
Purpose: Individual agent execution details within tasks| Column | Type | Constraints | Description |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | Execution ID |
| task_execution_id | UUID | FK → task_executions | Parent task |
| agent_id | VARCHAR(255) | NOT NULL | Agent identifier |
| execution_order | INTEGER | NOT NULL | Execution sequence |
| input | TEXT | NOT NULL | Agent input |
| output | TEXT | Agent output | |
| mode | VARCHAR(50) | Execution mode | |
| state | VARCHAR(50) | FSM state | |
| tokens_used | INTEGER | DEFAULT 0 | Tokens consumed |
| cost_usd | DECIMAL(10,6) | DEFAULT 0 | Execution cost |
| model_used | VARCHAR(100) | LLM model | |
| duration_ms | INTEGER | Execution time | |
| memory_used_mb | INTEGER | Memory usage | |
| created_at | TIMESTAMPTZ | DEFAULT NOW() | Start time |
| completed_at | TIMESTAMPTZ | Completion time |
idx_sessions_user_idON (user_id)idx_sessions_tenant_idON (tenant_id)idx_sessions_expires_atON (expires_at)idx_sessions_external_idON ((context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULLidx_sessions_user_external_idUNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULLidx_sessions_not_deletedON (id) WHERE deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
tool_executions
Purpose: Tool invocation history and performance| Column | Type | Constraints | Description |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | Execution ID |
| agent_execution_id | UUID | FK → agent_executions | Parent agent |
| task_execution_id | UUID | FK → task_executions | Parent task |
| tool_name | VARCHAR(255) | NOT NULL | Tool identifier |
| tool_version | VARCHAR(50) | Tool version | |
| category | VARCHAR(100) | Tool category | |
| input_params | JSONB | Input parameters | |
| output | JSONB | Tool output | |
| success | BOOLEAN | DEFAULT true | Success status |
| error_message | TEXT | Error details | |
| duration_ms | INTEGER | Execution time | |
| tokens_consumed | INTEGER | DEFAULT 0 | Tokens used |
| sandboxed | BOOLEAN | DEFAULT true | WASI sandbox used |
| memory_used_mb | INTEGER | Memory usage | |
| executed_at | TIMESTAMPTZ | DEFAULT NOW() | Execution time |
idx_sessions_user_idON (user_id)idx_sessions_tenant_idON (tenant_id)idx_sessions_expires_atON (expires_at)idx_sessions_external_idON ((context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULLidx_sessions_user_external_idUNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULLidx_sessions_not_deletedON (id) WHERE deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
event_logs
Purpose: Streaming event storage for audit and replay| Column | Type | Constraints | Description |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | Event ID |
| workflow_id | VARCHAR(255) | NOT NULL | Workflow identifier |
| task_id | UUID | Task reference (nullable) | |
| type | VARCHAR(100) | NOT NULL | Event type |
| agent_id | VARCHAR(255) | Agent identifier | |
| message | TEXT | Event message | |
| payload | JSONB | DEFAULT '' | Event payload |
| timestamp | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | Event time |
| seq | BIGINT | Sequence number | |
| stream_id | VARCHAR(64) | Redis stream ID | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | Record creation |
idx_sessions_user_idON (user_id)idx_sessions_tenant_idON (tenant_id)idx_sessions_expires_atON (expires_at)idx_sessions_external_idON ((context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULLidx_sessions_user_external_idUNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULLidx_sessions_not_deletedON (id) WHERE deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
token_usage
Purpose: Detailed token usage tracking per task| Column | Type | Constraints | Description |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | Record ID |
| user_id | UUID | FK → users | User |
| task_id | UUID | FK → task_executions | Task |
| provider | VARCHAR(50) | NOT NULL | LLM provider |
| model | VARCHAR(255) | NOT NULL | Model name |
| prompt_tokens | INTEGER | NOT NULL | Input tokens |
| completion_tokens | INTEGER | NOT NULL | Output tokens |
| total_tokens | INTEGER | NOT NULL | Total tokens |
| cost_usd | DECIMAL(10,6) | NOT NULL | Cost in USD |
| created_at | TIMESTAMPTZ | DEFAULT NOW() | Record time |
idx_sessions_user_idON (user_id)idx_sessions_tenant_idON (tenant_id)idx_sessions_expires_atON (expires_at)idx_sessions_external_idON ((context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULLidx_sessions_user_external_idUNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULLidx_sessions_not_deletedON (id) WHERE deleted_at IS NULL
usage_daily_aggregates
Purpose: Pre-computed daily usage statistics| Column | Type | Constraints | Description |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | Record ID |
| user_id | UUID | FK → users | User |
| date | DATE | NOT NULL | Aggregation date |
| total_tasks | INTEGER | DEFAULT 0 | Total task count |
| successful_tasks | INTEGER | DEFAULT 0 | Successful count |
| failed_tasks | INTEGER | DEFAULT 0 | Failed count |
| total_tokens | INTEGER | DEFAULT 0 | Total tokens |
| total_cost_usd | DECIMAL(10,6) | DEFAULT 0 | Total cost |
| model_usage | JSONB | Model distribution | |
| tools_invoked | INTEGER | DEFAULT 0 | Tool invocation count |
| tool_distribution | JSONB | Tool usage distribution | |
| avg_duration_ms | INTEGER | Average task duration | |
| cache_hit_rate | DECIMAL(3,2) | Cache hit percentage | |
| created_at | TIMESTAMPTZ | DEFAULT NOW() | Record time |
idx_sessions_user_idON (user_id)idx_sessions_tenant_idON (tenant_id)idx_sessions_expires_atON (expires_at)idx_sessions_external_idON ((context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULLidx_sessions_user_external_idUNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULLidx_sessions_not_deletedON (id) WHERE deleted_at IS NULL
Additional Tables
tool_calls
Purpose: Legacy tool call tracking (use tool_executions instead)prompts
Purpose: Prompt versioning and A/B testinglearning_cases
Purpose: Reinforcement learning case storagesession_archives
Purpose: Long-term session snapshots from Redisaudit_logs (public)
Purpose: Application audit trail (separate from auth.audit_logs)Database Functions
update_updated_at_column()
Purpose: Automatically updateupdated_at on row changes
Usage: Attached as trigger to users and sessions tables
update_daily_aggregate(user_id, date)
Purpose: Update or create daily usage aggregate for a user Usage: Called automatically via trigger on task completiontrigger_update_daily_aggregate()
Purpose: Trigger function to update aggregates on task status changes Usage: Automatically fires on task_executions INSERT/UPDATESample Queries
Task Analytics
Cost Analysis
Performance Monitoring
Best Practices
1. Indexing
Always use indexes for:- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
2. Partitioning
For high-volume tables, consider partitioning:3. Data Retention
Recommended policies:- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL
- UNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULL