ADR-0001: Frappe as the Single Source of Truth for Business Data¶
Status: Accepted Date: 2026-05-03 Deciders: Architecture team Impacted Repos: All
Context¶
The platform was historically split:
bz-api-server(NestJS + DynamoDB) held business data via single-table design.- Frontends (
bz-customer-web,admin-web-app, etc.) held duplicated state in Redux, local databases, and ad-hoc caches. - Migration to Frappe + MariaDB began in 2025.
- During migration, two parallel "sources of truth" coexisted, causing drift.
Without a clear rule, frontend teams kept adding business entities to local databases (e.g., Drizzle/TiDB tables for "packages", "outlets") because it was faster than waiting for a Frappe doctype. This created multiple drift risks: schema divergence, stale data, and re-implementation of business logic across repos.
Decision¶
Frappe (reservation-api-server) is the sole source of truth for all
business domain data. Every BookingZone repo treats Frappe as canonical.
Local stores are restricted to:
- Authentication / session state
- UI-only operational data (form builder content, AI logs, page builder)
- Caching of Frappe data, explicitly labeled as cache
- Data without any conceivable Frappe equivalent
If a new business concept emerges, the workflow is:
- Create or extend a
BZ*doctype inreservation-api-server. - Expose a whitelisted API method.
- Frontends consume via the published API contract.
Local Drizzle/TiDB tables for business data are forbidden and any PR introducing them is rejected.
Consequences¶
Positive¶
- Single source of truth eliminates drift.
- AI agents in any repo can rely on Frappe + the published contract.
- Simplifies migration completion (no parallel stores to reconcile).
- Auditability and compliance posture improves materially.
Negative / Trade-offs¶
- New features may be slower in the short term — must wait for backend doctype + API method before frontend can build against it.
- Frontends must handle Frappe API latency and intermittent failures rather than reading from a local DB.
Risks / Mitigations¶
- Risk: backend becomes a bottleneck for feature delivery. Mitigation: backend roadmap prioritizes new doctypes; frontends scaffold against generated types in parallel using stubs.
- Risk: cache layers become a hidden source of truth themselves. Mitigation: caches are explicitly labeled, time-bound, and never authoritative; every cache key resolves to a Frappe primary key.
Alternatives Considered¶
- Federated multi-master: each repo owns part of the schema. Rejected: introduces irreconcilable drift, complicates cross-repo reporting.
- Backend-for-Frontend with local persistence: keep light per-repo stores synced to Frappe. Rejected: doubles the schema work and the drift risk we are trying to eliminate.
Implementation Notes¶
- Existing local Drizzle tables for business data in
admin-web-appare flagged for migration to Frappe doctypes (separate spec required). - Caching pattern reference:
server/atp-frappe-packages.tsinadmin-web-app.
References¶
system-constitution.mdPrinciple Iadmin-web-app/FRAPPE_ONLY.md(legacy single-repo enforcement)