Database
This page covers database mode selection for OpenReader.
Scope of this page
- Focus: SQL metadata, state, and relational tables.
- Not covered here: object key layout and blob transport details (see Object / Blob Storage).
Database mode
- SQLite (default): embedded DB at
docstore/sqlite3.db; good for local/self-host single-instance setups. SetSQLITE_DB_PATHto override the file location. - Postgres: enabled when
POSTGRES_URLis set; recommended for production/distributed deployments.
What the database stores
- Document metadata/state used by server routes.
- Auth/session tables (
user,session,account,verification) when auth is enabled — schema is auto-generated by Better Auth. - Compute admission, usage, and idempotency state (
compute_limit_admissions,compute_limit_buckets, andcompute_limit_events). - User settings preferences (
user_preferences) when auth is enabled. - User reading progress (
user_document_progress) when auth is enabled. - Document preview job/asset metadata (
document_previews) for server-side PDF/EPUB thumbnails. - Playback session/cursor state is worker-owned; the app database no longer stores TTS segment or audiobook tables.
App-specific tables are manually maintained in Drizzle schema files, while auth tables are generated by the Better Auth CLI. Both are migrated together via Drizzle. See Migrations for details.
What the database does not store
- Raw document file bytes
- Audiobook export bytes
- TTS playback audio/sidecar bytes
- Generated preview image bytes
Those payloads live in object storage. SQL stores the metadata, references, and status.
Related variables
POSTGRES_URLSQLITE_DB_PATH(SQLite mode only; relative paths resolve from the app workspace)
For database variable behavior, see Environment Variables.
Related docs
State sync summary
- Settings and reading progress are stored in SQL and synced from the app.
- Sync is currently request-based (not realtime push invalidation).