Files
zarinpal-analytics-backend/docs/decisions/0011-lazy-merchant-analytics-cache.md

2.0 KiB

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.