Tables at a glance
Identity and events
Commerce
Configuration
Operations
Logical relations
The schema declares no database-level foreign keys. Every cross-table link is a string id, and most tables use composite natural keys scoped by shop (for example shop + product id + session id). Store isolation is enforced by every query filtering on the shop column, which is regression-tested.SQLite specifics that matter to maintainers
- DateTimes are epoch-millisecond integers. Prisma stores SQLite datetimes
as integer milliseconds, and the metrics code relies on it: time buckets are
computed with integer division, and raw
MAX()results are converted back to dates explicitly. - Money is BigInt cents. Order totals, refunds, prices, and rollup revenue
are stored as integer cents and surface as JavaScript
BigInt. - Raw SQL uses tagged templates only (
$queryRaw), never string concatenation. - SQLite serializes writes, not reads. The view-dedupe check-then-insert is wrapped in a per-key in-process promise chain to close the race; this is one of the single-instance assumptions documented in Security.
- Dev and production databases are separate files (
dev.sqlitelocally,/data/prod.sqliteon the deployment volume). Integration tests share the dev database and therefore run sequentially.
Data lifecycle
Deletion matrix
Prune and deletion jobs run inside the scheduler — see
Background jobs. The retention window is
merchant-configurable under Settings.