SD System Design In Depth
0%
lesson system-designanalyticsimpressions

Impression counting

Module 4.3: Probabilistic Sketches & Stream Analytics Updated Sep 17, 2026
📄 Cheat Sheet
Design an Ad Click Aggregator w/ a Ex-Meta Staff Engineer System Design Interview
Hello Interview Design an Ad Click Aggregator w/ a Ex-Meta Staff Engineer System Design Interview Watch on YouTube ↗

The canonical ad event aggregation walkthrough: durable ingest, Flink windowing, idempotency, reconciliation and OLAP serving, all central to impression counting.

0:00 / --:--

Scaling Ad Impressions

Impression counting is critical for advertising platforms. Advertisers pay per 1,000 impressions (CPM), so accuracy translates directly to revenue. Unlike standard view counting, losing an ad impression means losing money.

The Data Pipeline

When an ad renders, a pixel fires a request. The ingest servers must acknowledge this immediately. They write the event to a highly durable write-ahead log (like Kafka) before returning 200 OK. From there, Stream Processing engines (Spark Streaming, Flink) group events by Ad ID, Campaign ID, and time window.

Handling Late Data

In mobile environments, users go offline. An impression might happen at 2:00 PM, but the device only connects and sends the event at 4:00 PM. The system must support Event Time processing. It maintains "watermarks" to decide when a time window can be closed, but allows late-arriving data to update historical tables.

Database Choice

Real-time OLAP (columnar analytical) databases like Druid, Pinot, or ClickHouse are the industry standard for this; they are distinct from time-series databases such as Prometheus, InfluxDB or TimescaleDB, though they handle time-partitioned event data well. They ingest massive streams of data, organize it by time, and support sub-second analytical queries (e.g., "Show impressions for Campaign X broken down by hour").

Worked example: volumes

QuantityAssumptionResult
Impressions per day10 billionabout 116,000 per second average, 300,000 or more at peak
Raw event sizeAbout 200 bytesabout 2 TB per day
Minute aggregates1 million active ads, sparse, only minutes with trafficat most 1.44 billion rows per day, typically far fewer
Revenue at 2 dollars CPM10 billion divided by 1,000 x 220 million dollars per day; a 1 percent double count is 200,000 dollars per day of wrongful billing

Pipeline

flowchart LR A["Ad SDK fires impression with unique ID"] --> B["Ingest service"] B --> C["Kafka, replicated"] C --> D["Flink: dedup by impression ID, window by event time"] D --> E["OLAP store: Druid, Pinot or ClickHouse"] C --> F["Object storage raw archive"] F --> G["Daily batch recompute"] G --> H["Reconciliation and invoicing"] E --> H

Late data policy

Arrival delayHandling
Within watermark, for example 5 minutesCounted in the live window
Within allowed lateness, for example 24 hoursEmitted as a correction to the historical bucket
Beyond allowed latenessRouted to a late-data table; included in batch reconciliation or dropped per contract

Definitions matter

The Media Rating Council viewability guideline counts a display ad as viewable when at least 50 percent of its pixels are in view for at least one continuous second, and a video ad at 50 percent for two continuous seconds. Systems usually store both "served" and "viewable" impressions as separate measures, because advertisers may buy on either.

Dedup at scale: keep impression IDs in keyed state with a TTL a little longer than the allowed lateness; at hundreds of thousands of events per second over 24 hours that is billions of keys, so state lives in RocksDB-backed Flink state, not heap memory.

Interview framing

Lead with correctness requirements: at-least-once ingest plus dedup equals effectively-once counting; event-time windows; and a batch reconciliation that is the source for invoices. Then discuss the query side: advertisers want per-campaign, per-hour breakdowns with sub-second latency, which is why pre-aggregated rollups live in an OLAP store rather than being computed from raw events on each dashboard load.

Check yourself Question 1 of 3
Event-time bucketing recall
From: Scaling Ad Impressions

An ad is shown on a phone at 14:00, but the device is offline and the impression event reaches the servers at 16:00. In which hourly bucket should it be counted for billing?

Key Takeaways

Impression counting directly impacts revenue, requiring high durability.
Systems must handle late-arriving events using Event Time logic.
Real-time OLAP databases (Druid, Pinot, ClickHouse) are ideal for querying ad metrics.
Was this lesson helpful? Spot an issue or have a suggestion? Let us know on GitHub.
Report an issue