# ADR 0011: Calculate and cache merchant analytics lazily - Status: Accepted - Date: 2026-08-20 ## Context The hackathon dataset is static after its one-time bootstrap. Continuously refreshing analytics would spend resources before any merchant requests the data. The production boundary may later receive new append-only rows written directly by ZarinPal, bypassing Go request handlers, so any invalidation contract must also work at the database boundary. ## Decision Calculate a merchant's approved analytics projections on the first relevant dashboard request and persist typed projections in PostgreSQL. Reuse them while their merchant source revision, relevant cohort revision, and metric-definition version remain current. Schema-owned database logic atomically increments the affected merchant revision whenever a related payment fact is inserted. Inserts that affect peer benchmarks also increment the corresponding category/cohort revision. This covers direct ZarinPal writes without a refresh worker or Redis. On a cache miss or revision mismatch, the backend obtains a merchant-scoped PostgreSQL advisory/row lock, computes the projections once, publishes them atomically, and then advances the cached revision. Concurrent requests wait for or reuse that result. A failed calculation does not advance the cached revision; an older snapshot may be returned only when clearly marked stale. Payment facts are append-only for this MVP. Cache invalidation for updates or hard deletion is out of scope and requires a future contract change. ## Consequences - The static dataset is aggregated at most once per merchant and metric-definition revision when requested. - No scheduled analytics worker, nightly reconciliation, Redis, or time-based cache expiry is required. - Cache correctness is version-based, not age-based. - Cohort revision tracking prevents a new merchant fact from silently leaving peer comparisons current for other merchants. - Trigger/revision behavior, concurrency deduplication, failure recovery, and traceability require integration tests.