- **better-sqlite3**: High-performance SQLite driver. Multi-step writes use `db.transaction()`.
- **Multer**: Multi-part form data handling for photo and document uploads (type + size limits enforced).
- **Authentication**: Deliberately not implemented — BREEDR is a self-hosted LAN app. Revisit as its own feature if exposure changes (decision: July 2026).
The database is a single file at `data/breedr.db` by default; both the migration runner and the app honor `DB_PATH`, and the containing directory is created automatically on startup.
**Benefits**: Supports recursive lookups, avoids `ALTER TABLE` complexity for lineage changes, and allows historical mapping of ancestors without full profiles.
BREEDR uses a two-layer synchronization approach, both run at startup (`server/index.js`):
1.`server/db/migrations.js` — a versioned migration runner for structural rewrites (e.g. moving sire/dam into the `parents` table). Migrations no-op on a fresh/empty database.
2.`server/db/init.js` — defines the latest table structures (`CREATE TABLE IF NOT EXISTS`) and injects missing columns with safe `ALTER TABLE` guards.
> ⚠️ **Keep init.js in sync with the routes.** The schema drifted once (routes wrote columns init.js never defined) and only worked because the live Docker volume carried an older ad-hoc schema — fresh installs were broken. When adding a column a route writes, add it to the `CREATE TABLE` *and* the ALTER-if-missing list. Verify by booting against a deleted/renamed dev DB.
- Both providers wrap the app in `App.jsx`. Page loaders should use `Promise.allSettled` + an error banner with Retry rather than silently swallowing fetch failures (see `Dashboard.jsx`, `BreedingCalendar.jsx`).