# ADR 0008: ZarinPal owns live writes; analytics refresh within 15 minutes - Status: Accepted - Date: 2026-08-20 ## Context The challenge archive is a one-time bootstrap source. In production, ZarinPal already creates payment data and will write future records directly to the normalized PostgreSQL schema. Building a recurring CSV importer, polling source, or competing payment-write workflow would duplicate upstream responsibility. Derived dashboard projections still need bounded freshness and correction when live source rows arrive or change status. ## Decision ZarinPal is the authoritative producer of live `payment_sessions` and `payment_attempts`. This backend owns the normalized schema contract, versioned migrations, analytical reads/projections, and tenant-safe APIs, but not the business workflow that produces live payment records. Fact rows identify `bootstrap` versus `zarinpal_live` origin. Bootstrap rows reference import provenance; live rows do not fabricate import runs. The live-write contract supplies stable creation/update metadata so an idempotent high-watermark process can include new rows and status updates. Refresh affected analytics projections within 15 minutes. Run a nightly idempotent reconciliation over an approved authoritative window to detect and correct missed/changed rows. Publish projections atomically and advance the visible freshness watermark only after success. ## Consequences - No recurring CSV ingestion service, file watcher, or source polling is built. - Schema migrations require compatibility coordination with ZarinPal's writer. - Analytics refresh is separate from ingestion and requires scheduling, checkpoints, idempotency, metrics, and stale-state UX. - If upstream cannot provide reliable update metadata, revise the refresh algorithm/window before implementation rather than silently missing mutations. - The static hackathon dataset builds projections once after bootstrap; production scheduling remains testable with synthetic live writes.