Skip to main content
Version: v5.0.0

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. Set SQLITE_DB_PATH to override the file location.
  • Postgres: enabled when POSTGRES_URL is 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, and compute_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.

  • POSTGRES_URL
  • SQLITE_DB_PATH (SQLite mode only; relative paths resolve from the app workspace)

For database variable behavior, see Environment Variables.

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).