This article details how Netflix re-architected its Ads Event Publisher, moving from a database lookup-based enrichment system to a stateful stream processing solution using Apache Flink. The evolution was driven by the demanding scale and spiky traffic patterns of live streaming, focusing on removing critical path dependencies, improving scalability, and ensuring event freshness. The new architecture leverages real-time streaming joins to match ad serving responses with client events, enhancing efficiency and resilience.
Read original on Netflix Tech BlogNetflix's Ads Event Pipeline is a critical system for collecting, enriching, and distributing ad telemetry. Initially, it used a centralized system called Ads Event Publisher that relied on a globally replicated Key-Value store, the Ads Metadata Registry, for enriching client ad events with detailed serving context. While effective for Video on Demand (SVOD), this design faced significant challenges when scaling for live streaming events, which exhibit massive, spiky traffic patterns.
To address these limitations, Netflix rebuilt the Ads Event Publisher around stateful stream processing using Apache Flink. The core idea was to shift the metadata lookup from a synchronous database write on the critical path to an asynchronous, real-time streaming join. This allows the ad server to simply log its responses to Kafka, and the Flink job then matches these responses with client events downstream, off the critical path.
Why Apache Flink?
Netflix chose Apache Flink due to its strengths in near-real-time, stateful stream processing and its existing, mature production support within Netflix. This allowed the team to leverage prior experience with Flink (e.g., Ads Sessionizer) for operating, tuning state, checkpoints, and recovery under production load, accelerating development and deployment.
The new architecture centers on an Apache Flink streaming job with several key stages: normalization, re-routing, joining, deduplication, and publishing. The join stage is the most critical, matching client events (carrying an opaque token) with ad-serving responses (containing full metadata) using a custom Flink KeyedCoProcessFunction. This function holds recent responses in memory for up to 60 minutes, ensuring high match rates while managing state efficiently. Cross-region challenges are handled by encoding the serving region into the ad token and routing client events to the correct region for joining, minimizing global data replication.
This re-architecture not only solved the scalability issues for live events but also reduced critical path dependencies, improved event freshness, and provided a more flexible and resilient pipeline for future advertising growth at Netflix.