Skip to content

Database Schema

MealPal uses PostgreSQL with pgvector on AWS RDS (ca-central-1). Two databases on the same instance:

  • mealpal — meals, chat, RAG embeddings, metrics
  • auth — Better-Auth tables (users, sessions, JWKS, 2FA)
  1. User-Centric — all data anchored to users with proper foreign keys
  2. Immutable History — meal logs never deleted, only soft-deleted
  3. Flexible Metadata — JSONB for extensible data (nutrition, AI responses)
  4. Performance First — strategic indexes on all query patterns
  5. Privacy Ready — easy to export/delete user data (GDPR compliant)
erDiagram
users ||--o{ meal_logs : "logs"
users ||--o{ user_goals : "has"
users ||--o{ user_preferences : "has"
users ||--o{ conversations : "chats"
users ||--o{ api_usage : "tracks"
meal_logs ||--o{ meal_foods : "contains"
conversations ||--o{ messages : "contains"
ColumnTypeNotes
idUUID PK
auth_idstring UKFrom Better-Auth
emailstring UK
tierstringfree or premium
created_attimestamp
ColumnTypeNotes
idUUID PK
user_idUUID FK
meal_timetimestampWhen they actually ate
meal_typestringbreakfast/lunch/dinner/snack
nutrition_totalsJSONBcalories, macros, micros
ai_analysisJSONBFull AI response
image_urlstringS3 URL
is_deletedbooleanSoft delete
ColumnTypeNotes
conversations.idUUID PK
conversations.titlestringAuto-generated from first message
messages.rolestringuser or assistant
messages.contenttext
messages.message_metadataJSONBCitations, referenced meals

Tracks AI provider costs per request (provider, model, tokens, cost_usd).

-- Most queried: meals by user and time
CREATE INDEX idx_meal_logs_user_time ON meal_logs(user_id, meal_time DESC);
CREATE INDEX idx_meal_logs_deleted ON meal_logs(user_id, is_deleted) WHERE is_deleted = false;
-- API cost tracking
CREATE INDEX idx_api_usage_user_date ON api_usage(user_id, created_at DESC);
  • JSONB for nutrition — flexible schema, fast querying with GIN indexes, no 50+ columns
  • Soft delete — preserves history for analytics, supports undo, GDPR-compliant purge
  • user_id everywhere — easy data export, simple row-level security