Database

Engine

PostgreSQL via Supabase with Drizzle ORM for type-safe queries.

ORM & Query Layer

LayerLocationUse Case
Drizzle ORMpackages/db/src/drizzle/Type-safe queries, transactions, complex joins
Supabase Clientpackages/db/src/client.tsAuth, Storage, RLS-dependent operations
Query Cachepackages/db/src/cache.tsRedis caching for hot paths (plan lookups)

Drizzle Setup

# Connection string (Supavisor transaction mode)
DATABASE_URL=postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres

Type Generation

bun run db:types  # Generate types from Supabase schema

User & Subscription Tables

TableDescriptionRLS
profilesUser profiles synced from Supabase AuthYes
plan_definitionsPlan configuration (free, base, pro, team, plus)Yes (read-only)
user_subscriptionsMaps users to plans with Stripe integrationYes
notification_preferencesPer-user notification settingsYes
system_notificationsSystem-generated notificationsYes
feature_flagsRuntime feature flag togglesNo
ai_model_tier_configAI model routing configuration per tierNo

Fact Engine Tables (V2)

The V2 fact engine introduces a knowledge platform built on hierarchical taxonomy, structured facts, and interactive challenges.

Taxonomy

TableDescriptionRLS
topic_categoriesHierarchical taxonomy tree (depth 0-3, slug, path, dailyQuota). Supports deprecation via deprecated_at, replaced_by, deprecation_reason columns.No
topic_category_aliasesMaps external provider slugs (e.g., NewsAPI business) to canonical topic category IDsNo
unmapped_category_logLogs category slugs that could not be resolved — used for periodic audit and alias creationNo

Fact Storage

TableDescriptionRLS
fact_recordsCore fact storage — facts JSONB with key-value pairs, title, context, notabilityScore, status, validation JSONBYes
fact_record_schemasPer-topic fact shape definitions — factKeys JSONB defining typed fields, cardFormats arrayNo

Challenge System

TableDescriptionRLS
fact_challenge_contentPre-generated challenge text per style/difficulty with challenge_titleYes
challenge_formats8 named challenge formats with knowledgeType and toneNo
challenge_format_stylesFormat → eligible style mappingNo
challenge_format_topicsFormat → eligible topic mappingNo
challenge_sessionsMulti-turn conversational challenge state with conversation historyYes
card_interactionsUser engagement tracking (views, answers, bookmarks, shares)Yes
challenge_group_progressPer-position progress within challenge groupsYes
card_bookmarksUser bookmarked cardsYes
score_disputesUser score dispute submissions for AI re-evaluationYes
reward_milestonesAchievement milestones for gamificationNo
user_reward_claimsClaimed milestone rewardsYes
user_quality_gradesPer-topic quality grade aggregationYes

Ingestion & Observability

TableDescriptionRLS
storiesClustered news articles grouped by TF-IDF cosine similarityNo
news_sourcesRaw articles fetched from news APIsNo
ai_cost_trackingPer-model, per-feature daily cost aggregationNo
ingestion_runsPipeline observability — tracks each cron invocation with status and metricsNo
content_operations_logOperational event log for pipeline debuggingNo

Seed Pipeline

TableDescriptionRLS
seed_entry_queueBatch seed entry processing queueNo
super_fact_linksCross-entry correlation linksNo
seed_entry_linksEntry-to-fact provenance linksNo

Brand & Domain

TableDescriptionRLS
brandsCanonical brand entitiesNo
domainsDomain records with verification statusNo
brand_categoriesBrand categorization taxonomyNo
brand_category_assignmentsBrand → category mappingsNo

See Fact & Taxonomy Schema Map for the full schema reference including Zod schemas, AI types, and worker handlers.

Migrations

Location: supabase/migrations/

The project has 167 migration files numbered up to 0174, spanning foundation schema (V1), vNext global URL library, V1 cleanup, and the V2 fact engine. See Migrations Index for the full listing organized by phase.

Key migration phases:

  • 0001-0017: Foundation — core tables, RLS, brand library, vNext
  • 0018-0056: Features & vNext — fact engine schema, challenge system, ingestion pipeline
  • 0057-0060: V1 cleanup — 41 legacy tables dropped
  • 0061-0174: V2 development — taxonomy expansion, challenge groups, points/grading system, evidence enrichment, seed pipeline

Conventions:

  • Forward-only SQL (no rollback)
  • 4-digit zero-padded numbering
  • RLS enabled by default for user tables
  • Use CONCURRENTLY for index creation

Access Patterns

RoleTablesUse Case
Anon/AuthenticatedCore tables (via RLS)User reads/writes
Service roleAll tablesWorkers, admin, Brand Library

Query Caching

Hot paths are cached using Upstash Redis with in-memory fallback:

FunctionTTLDescription
getCachedUserPlan()5 minUser plan lookups (every auth request)
getCachedPlanDefinitions()1 hourPlan definitions (rarely change)

Invalidate cache when subscriptions change: invalidateUserPlanCache(userId)

Backups

Supabase managed. Verify before destructive migrations.


Related docs: