Design an Ad Click Event Aggregation System
The clickstream told PhoenixWorld what users do. Ads are how PhoenixWorld gets paid for it: sellers bid to promote their products, and PhoenixWorld charges them for every click their ad receives. The moment money rides on a number, the whole game changes. A dashboard that is approximately right is fine; an invoice that is approximately right is a refund request, a support ticket, and eventually a lawsuit. "Count the ad clicks per campaign per minute" sounds like a warm-up, which is exactly why it is the most-asked data engineering interview question - every hard streaming idea hides inside it.
PhoenixWorld's ad platform bills sellers per click and finance sends invoices at month end. Rafael owns the counting. The naive version - increment a counter in Redis per campaign - demos beautifully and then meets the three things that always happen in production: the same click arrives twice because a phone retried, a click arrives four minutes late because that phone was in an elevator, and a Black Friday campaign draws a hundred times the clicks of every other campaign and melts the one partition it lands on. Each of those, left uncorrected, is money moving the wrong way.
The tension that shapes the whole design: a seller wants a near-real-time view of spend so they can pause a campaign that is burning budget, and finance wants an invoice that is exactly right weeks later. Those are two different correctness bars, and the senior move is to serve both honestly instead of pretending one system does both jobs. That is why billing pipelines run a fast stream and a slow batch and reconcile them - and why this problem is really about knowing which number to trust for what.
Step 1 - Understand the Problem and Establish Design Scope
"Count the clicks" hides a serving system, a billing system, and every out-of-order-and-duplicate trap in streaming. The clarifying questions separate them.
Candidate: What exactly are we counting, and along which dimensions?
Interviewer: Clicks per ad campaign, bucketed per minute. Sellers slice by campaign and want to filter by a couple of dimensions like country. Impressions are a separate system; focus on clicks.
Candidate: Who consumes the counts, and how correct does each need to be?
Interviewer: Two consumers. Seller dashboards showing near-real-time spend, where approximately right and quickly is fine. And monthly billing, where the number has to be exactly right, because we invoice real money against it.
Candidate: What's the volume?
Interviewer: Roughly 10 billion click events a day, bursty around sales. Design for the peak.
Candidate: How fresh does each consumer need to be?
Interviewer: The dashboard within a minute or so. Billing runs daily and finalizes monthly, so it can be a batch process.
Candidate: Do clicks arrive late or duplicated?
Interviewer: Both, constantly. Mobile clicks land minutes late with their original timestamp, and retries mean the same click can arrive more than once. A late click still has to count in the minute it actually happened.
Candidate: I'll assume basic invalid-click filtering is in scope, but a full fraud model is its own system.
Interviewer: Correct. Drop the obviously invalid ones; fraud scoring is out of scope.
That pins it down.
Functional requirements
- Ingest click events and count clicks per
(campaign_id, minute), queryable by a few dimensions. - Serve near-real-time aggregated counts to seller dashboards (spend, top campaigns).
- Produce exact, reconciled counts for monthly billing.
- Deduplicate retried clicks, and attribute a late click to the minute it actually happened.
- Filter obviously invalid clicks before they are counted.
Read the full breakdown
The deep dives, bottlenecks, and interview talking points are part of your subscription. Log in or join to keep reading.