ADR-0017: Infrastructure Migrations — PostgreSQL→D1 and Dexie→SQLite WASM
Status: accepted
Date: 2026-06-27
Supersedes: ADR-0008, ADR-0010, ADR-0001
Deciders: @barateza
Context
The Neemias backend originally ran on a Fastify/Node.js server with PostgreSQL (ADR-0008) and nightly pg_dump backups (ADR-0010). The frontend used Dexie/IndexedDB as the canonical client storage engine (ADR-0001).
Two migrations reshaped the architecture in 2025-2026:
PostgreSQL → Cloudflare D1 (2025 Q3-Q4) — The backend was rewritten as a Cloudflare Worker, and the database was migrated from PostgreSQL to D1 (SQLite at the edge). This eliminated server maintenance, simplified deployments, and aligned with the edge-native architecture.
Dexie/IndexedDB → SQLite WASM (2026 Q2) — The frontend storage was migrated from Dexie/IndexedDB to
@sqlite.org/sqlite-wasmwith OPFS persistence. This was the Storage Web Migration (SWM), tracked in issues #230-#295. The motivation was schema alignment with D1 (shared SQL DDL from Zod schemas) and eliminating the dual-write pattern (Dexie + D1 sync).
This ADR records both migrations so future architecture reviews have a single source of truth.
Decision
PostgreSQL → D1
- What changed:
workers/now handles all backend logic. The D1 database (c965d6fc-ee7e-41dd-bc81-65b05652aa17) is the source of truth. Migrations live inmigrations/and are applied viawrangler d1 migrations apply. - Why: Edge-native, zero-maintenance database. No more Docker Compose, no more
pg_dump. Backups are Cloudflare-managed. - Impact: ADR-0008 (PostgreSQL schema) is superseded. ADR-0010 (pg_dump backups) is superseded. The legacy Fastify server is archived at
docs/backend/legacy-fastify.md.
Dexie → SQLite WASM
- What changed: The
StorageBackendinterface now has a single implementation:SQLiteStore. Data is persisted via OPFS (opfs-sahpoolVFS) or MemoryVFS (tests). Dexie,dexie-react-hooks, and the repository pattern (db/repositories/) were removed. - Why: Shared schema with D1 — both use SQLite, both generated from the same Zod schemas in
@neemias/schemas. The Zod→SQL generator (generateSchemaSQL.ts) produces DDL for both environments. No more dual-write sync complexity. - Impact: ADR-0001 (Dexie storage) is superseded. The
DexieAdapterwas removed in #294. Thedexiepackage was removed in #295. - Reversal: ADR-0030 (2026-07-28) reverted this part — the frontend now uses Dexie/IndexedDB again. The SQLite WASM layer was removed in #510.
Consequences
Positive
- Single SQL dialect across frontend and backend (SQLite)
- Schema generated from Zod — impossible for frontend and backend to drift
- No more IndexedDB/Dexie version migration headaches
- OPFS persistence is more reliable than IndexedDB in Safari
Negative
- SQLite WASM bundle is larger than Dexie (~500KB gzipped vs ~70KB)
- OPFS requires a secure context (HTTPS or localhost)
- Cold start includes WASM instantiation (~50ms on first load)
- sqlite-wasm requires
'unsafe-eval'and'wasm-unsafe-eval'in Content-Security-Policy, relaxing script-src for the entire SPA. Mitigated by #314 (OnlineProxy) which keeps CSP strict when online.
References
- SWM Completion Spec
- SQLite WASM documentation
- Cloudflare D1 documentation
- Issues: #230 (SWM proposal), #294 (DexieAdapter removal), #295 (dexie removal)
- Commits:
9dd23af(DexieAdapter removed),8154a5e(dexie removed)