Start by clarifying requirements and scale, then propose a low-latency read path using an in-memory counter store with precomputed rolling windows. Discuss the write path with idempotent increments, hot-key mitigation, and offline reconciliation for accuracy. Finally, cover graceful degradation and trade-offs between consistency and availability.
Pro tip: Emphasize that the read path must be fast and approximate, while the write path ensures eventual accuracy; this separation of concerns is key to meeting latency and correctness goals.
Ask about expected QPS, latency targets, consistency requirements, and whether caps are per user-campaign or global. Understand the read/write ratio and data volume.
Propose an in-memory store (e.g., Redis) with keys like user:campaign:window and precomputed counts. Use rolling windows via bucketed time slots (e.g., hourly) and sum relevant buckets for day/week/month checks.
Increment counters asynchronously after impression render. Ensure idempotency using unique impression IDs and deduplication. Use a message queue for reliability and to decouple from ad serving.
Mitigate hot keys via sharding (e.g., user_id % N) or local caching with periodic sync. Consider using a distributed cache with replication and consistent hashing.
Implement graceful degradation: if counter store is unavailable, allow ads (fail-open) or block (fail-closed) based on business needs. Run offline reconciliation from logs to correct counts and handle discrepancies.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.