Start by clarifying requirements: read/write QPS, latency budget, accuracy tolerance, and failure semantics. Then propose a hybrid architecture: a fast in-memory counter store (e.g., Redis) with sliding window expiration for real-time decisions, backed by a durable store (e.g., Cassandra) for persistence and multi-region sync. Discuss trade-offs between exact and approximate counting, and define fallback behavior when the counter store is unavailable.
Pro tip: Emphasize that ad serving must never block on the counter store; use a local cache with short TTL and asynchronous updates to meet strict latency SLAs, and degrade gracefully by allowing ads when the store is down (fail-open) to avoid revenue loss.
Ask about QPS, latency budget (e.g., <10ms), accuracy tolerance, and consistency needs across regions. Confirm that the system must be highly available and that occasional over-serving is acceptable.
Propose using an in-memory store like Redis with sorted sets or time-bucketed counters for sliding window. For high QPS, shard by user-campaign and use pipelining or Lua scripts for atomic increments.
Use a local cache (e.g., in-process or sidecar) with short TTL to avoid remote calls on every ad request. Batch writes asynchronously to reduce write amplification, and consider approximate counting (e.g., Count-Min Sketch) to lower memory and write costs.
Implement sliding window via time-bucketed counters (e.g., per-minute buckets) and expire old buckets. For multi-region, use a primary region for writes with asynchronous replication, or CRDTs for eventual consistency, accepting temporary over-serving.
If the counter store is down, fail-open (allow ads) to avoid blocking revenue, but log and alert. Alternatively, use a local fallback counter with conservative limits. Ensure the system degrades gracefully without impacting ad serving latency.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.