5.2 KiB
ADR-006: Data Storage Strategy (SQLite vs PostgreSQL)
Status: Proposed
Date: 2026-08-02
Author: AI Assistant (following AGENTS.md, ADR-002, ADR-003, ADR-004, ADR-005)
Related ADRs: ADR-001, ADR-003, ADR-005, ADR-007
Context
The system needs persistent storage for:
- Chat messages and history (public rooms and private DMs).
- User accounts, roles, and ban lists.
- Moderation audit log (immutable record of admin and moderator actions).
- Playlist metadata and schedule overrides.
- System configuration (including Redis settings adjustable via admin UI per ADR-005/ADR-007).
From ADR-003 we prefer operational simplicity. ADR-005 requires a robust audit trail. We must decide between SQLite (embedded, zero-config) and PostgreSQL (full-featured, scalable) and document how the admin interface can view and adjust storage-related configuration.
Decision Drivers
- Operational Simplicity – Minimize infrastructure (no separate DB server for SQLite).
- Performance & Concurrency – Chat and moderation may have high write volume.
- Backup and Recovery – Easy point-in-time recovery and replication.
- Admin Capabilities – Admin UI must be able to view storage stats, run vacuum/analyze, and switch between SQLite and PostgreSQL (with migration path).
- Auditability – Moderation log must be immutable and queryable.
- Cost – Avoid managed database costs during early stages.
Decision
Primary storage for v1: SQLite (embedded in the chat and admin services).
Migration Path: Provide a clear upgrade path to PostgreSQL when concurrency or replication needs exceed SQLite capabilities (target v2 or when concurrent users > 500).
Admin Interface Capabilities (extension of ADR-005):
- "System Configuration" tab showing current storage engine, database size, connection stats, and vacuum status.
- Buttons to run
VACUUM,ANALYZE, or trigger a backup. - Configuration form to switch connection string (SQLite file path vs PostgreSQL URL) and restart services gracefully.
- Audit log of all configuration changes.
Technical Details:
- Use SQLite with WAL mode for better concurrency.
- Use GORM or sqlx (Go) or Prisma (if Node.js fallback) for ORM/migrations.
- Store large chat history in a separate table with retention policy (e.g., 30 days).
- Moderation log as an append-only table with triggers for immutability.
Folder Placement (per ADR-002):
- Database models and migrations in
backend/shared/db/orbackend/chat/internal/db/. - Admin UI pages for storage management in
frontend/admin/system/.
Rationale
- SQLite aligns with ADR-003's emphasis on operational simplicity and low resource usage for the initial deployment on a single Hetzner VPS.
- It eliminates the need for a separate database container in
docker-compose.ymlduring early development. - The admin interface can provide visibility and basic maintenance operations, fulfilling the requirement from the previous TODO plan.
- PostgreSQL can be introduced later with a migration script when scale demands it (replication, advanced querying, full-text search on chat).
Consequences
Positive:
- Zero-config database for quick local development and small-scale production.
- Simple backups (just copy the
.dbfile). - Admin UI can directly manage and monitor storage without external tools.
Negative / Risks:
- SQLite has limited concurrency compared to PostgreSQL (WAL mode helps but is not a full replacement).
- Large chat history or analytics queries may become slow – plan retention policy and archiving.
- Migration to PostgreSQL will require downtime or dual-write strategy (documented in this ADR).
Alternatives Considered:
- PostgreSQL from day one – rejected for added operational complexity (separate service, connection pooling, managed service cost).
- Pure key-value store (e.g., BoltDB) – rejected because SQL is better for audit logs and complex moderation queries.
- Managed database (Neon, Supabase) – rejected to maintain full self-hosted independence per ADR-001.
Implementation Plan
- Create this ADR-006 (done).
- Add SQLite support in
backend/shared/db/with GORM migrations. - Implement admin UI pages for storage monitoring and configuration (linked to ADR-005).
- Add configuration reload capability without full restart where possible.
- Write migration script from SQLite to PostgreSQL.
- Update
docker-compose.ymlto optionally include PostgreSQL. - Add tests for data access patterns and admin configuration changes.
Next ADR: ADR-007 (Redis usage and admin configuration capabilities).
References
- ADR-001: Chat persistence, moderation log, monitoring requirements.
- ADR-003: Preference for operational simplicity and Go backend.
- ADR-005: Admin interface for user management, moderation, and analytics – this ADR extends it with storage and Redis config capabilities.
- arc42 documentation: Cross-cutting Concepts (data management, monitoring) and Risks & Technical Debts.
This ADR ensures all data storage decisions are documented before code is written, maintaining full traceability.