This one sprawled in ways I didn't anticipate.
Start by clarifying requirements and scale, then propose a low-latency, eventually consistent counter store using a time-bucketed data model. Discuss trade-offs between consistency, availability, and latency, and outline fallback strategies for store failures.
Pro tip: Emphasize that ad frequency capping is a business decision: sometimes serving an ad slightly over the cap is acceptable to avoid under-delivery, so design for graceful degradation rather than strict consistency.
Ask about expected QPS, latency SLA, consistency needs, and failure tolerance. Confirm the granularity (ad, campaign, advertiser) and time windows (e.g., hourly, daily).
Propose a key-value store with composite keys (e.g., user_id:entity_type:entity_id:time_bucket) and counters. Use time-bucketed counters to enable efficient windowed queries and TTL-based cleanup.
Use an in-memory store (e.g., Redis) with pipelining and sharding to handle high write throughput. For reads under 10ms, keep counters in memory and use local caching with short TTLs.
Choose eventual consistency with asynchronous replication across regions. Discuss conflict resolution (e.g., last-write-wins or CRDTs) and how to handle regional failover.
If the cap store is down, fall back to serving ads without caps (or with a local cache) to avoid revenue loss. Implement circuit breakers and monitoring to detect failures quickly.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.