Database
Hitler uses PostgreSQL with Drizzle ORM for type-safe database access.Schema Overview
Entity Relationships
Foreign Key Constraints
All FK constraints are designed for safe deletion without leaving orphaned data.CASCADE Delete (child deleted when parent deleted)
| Parent | Child | Reason |
|---|---|---|
users | platform_identities | User’s platform links are meaningless without user |
tasks | task_logs | Task history is meaningless without task |
inquiry_threads | inquiry_messages | Messages are meaningless without thread |
SET NULL on Delete (reference nullified, record kept)
| Parent | Child Column | Reason |
|---|---|---|
task_drafts | tasks.draftId | Allow draft cleanup, task keeps its data |
users | flags.resolvedBy | Keep flag history even if resolver leaves |
users | inquiry_messages.senderId | Keep message even if sender deleted |
flags | inquiry_threads.flagId | Keep thread even if flag resolved/deleted |
Why This Matters
Without proper ON DELETE actions:- You can’t delete task drafts that have been confirmed (FK violation)
- You can’t delete users who have sent inquiry messages
- You can’t clean up old data without manual cascading
Automatic Data Cleanup
Scheduled jobs automatically clean up old data to prevent database bloat.Task Drafts Cleanup (Daily at 2 AM)
- Audit trail: see what user said vs what LLM parsed
- Debugging: investigate if task was created incorrectly
- After 30 days, the task itself is the source of truth
Channel Messages Cleanup (Daily at 2 AM)
- Raw messages are processed into context_observations within minutes
- Observations contain the extracted intelligence; raw text is no longer needed
- Keeps storage costs manageable for high-volume channels
Security Audit Logs Cleanup (Monthly)
- Sufficient for security investigations
- Compliance with typical log retention policies
- Prevents unlimited growth
pgvector Extension
The database uses the pgvector extension for vector similarity search. This powers the context memory system’s semantic search capabilities.Setup
The Docker Postgres image ispgvector/pgvector:pg16 (not the standard postgres:16-alpine). The migration creates the extension:
Vector Columns
Two tables usevector(1536) columns for OpenAI text-embedding-3-small embeddings:
context_observations.embedding— per-observation semantic vectorcontext_summaries.embedding— per-entity-summary semantic vector
HNSW Indexes
HNSW (Hierarchical Navigable Small World) indexes enable fast approximate nearest neighbor search:Similarity Search
Queries use the cosine distance operator (<=>):
Migrations
Drizzle generates migrations automatically when schema changes.Migration Files
Indexes
All tables have performance indexes defined in their schema files.Key Indexes
tasks:user_id- Filter by userorganization_id- Filter by orgstatus- Filter by status(user_id, status)- Composite for user’s pending tasksdue_date- Sort/filter by due datecreated_at- Sort by creationclient_id- Filter by clientstage_id- Filter by pipeline stage(organization_id, display_id)- Unique org-scoped display IDs
organization_id- Filter by org(organization_id, position)- Ordered stage listing- Unique
(organization_id, slug)- Prevent duplicate slugs per org
user_id- Filter by userorganization_id- Filter by orgexpires_at- Cleanup job efficiency
user_id- Filter by userrecorded_at- Time-based queries(user_id, recorded_at)- User’s mood history
user_id,organization_id- Basic filteringseverity,status- Dashboard queries(user_id, status)- User’s active flags
organization_id- Org dashboardthreat_level- Severity filteringcreated_at- Time-based cleanup(organization_id, threat_level, created_at)- Dashboard queries
Best Practices
Adding New Tables
- Define schema in
packages/db/src/schema/ - Export from
packages/db/src/schema/index.ts - Add appropriate FK constraints with ON DELETE actions
- Add indexes for common query patterns
- Generate and apply migration
FK Constraint Guidelines
When to Use Each
| Use Case | ON DELETE |
|---|---|
| Logs/audit trail for entity | CASCADE |
| Optional reference (can be null) | SET NULL |
| Reference to lookup/config table | NO ACTION |
| User-created content referencing user | SET NULL |
Manual Cleanup
If you need to manually clean up data:Troubleshooting
”Cannot delete: FK constraint violation”
This means a child table references the record. Check:- Is the FK set up with proper ON DELETE action?
- If not, delete children first, then parent
- Or update the schema and run migration