मुफ़्त पूरी गाइड

विज्ञापन क्लिक एग्रीगेटर

विज्ञापन क्लिक एग्रीगेटर डिज़ाइन करें। इसमें High-throughput ingestion of K-M clicks/sec via a log/stream (Kafka) before aggregation, Exactly-once vs at-least-once delivery and idempotent aggregation...

00

अभ्यास checkpoints

Interview की लय संक्षिप्त रहती है, ताकि page असली design निर्णयों पर ध्यान लगा सके.

  1. 01
    Scope स्पष्ट करें
  2. 02
    Requirements + scale
  3. 03
    API + data model
  4. 04
    Architecture बनाएँ
  5. 05
    Deep dive
  6. 06
    Trade-off निर्णय
01

Requirements जो design तय करते हैं

सिर्फ requirements मत बताइए — पूछिए। हर card एक design constraint को उस clarification सवाल से जोड़ता है जो आप architecture बनाने से पहले बोल सकते हैं.

Functional requirements

01एक क्लिक आख़िर किससे गिना जाता है — उपयोगकर्ता का tap, या advertiser साइट पर पहुँचना?

उपयोगकर्ता एक विज्ञापन पर क्लिक करते हैं और उन्हें advertiser साइट पर 302 redirect मिलता है — क्लिक उसी hop पर server-side रिकॉर्ड होता है, इसलिए ad blocker और अस्थिर client उसे खो नहीं सकते।

02Advertiser को कितनी granularity और freshness चाहिए?

Advertiser समय के साथ क्लिक मेट्रिक्स को कम-से-कम एक मिनट की granularity पर query कर सकते हैं, और क्लिक के लगभग एक मिनट के भीतर वह उपलब्ध होता है।

03अगर वही क्लिक दो बार आए — double-tap या retry — तो क्या वह एक ही गिना जाना चाहिए?

एक ही impression पर duplicate क्लिक एक ही गिना जाता है — हर दिखाए गए विज्ञापन में पहले से एक unique impression ID होता है।

04सिर्फ़ क्लिक, या impressions और CTR भी?

पहले क्लिक। Impressions और CTR (click-through rate) बाद में एक जानी-पहचानी अगली ज़रूरत के तौर पर आते हैं।

05एक मिनट से आगे कौन-सी granularity — घंटे, दिन?

विज्ञापनदाता घंटे और दिन के view भी देखते हैं; एक मिनट ही सबसे बारीक granularity रहती है।

06क्या budget cap को विज्ञापन near real time में रोकने चाहिए?

हाँ — budget cap तक पहुँचा विज्ञापन लगभग एक मिनट के भीतर serve होना बंद होना चाहिए।

Scope से बाहरविज्ञापन targeting और ad serving (कौन-सा विज्ञापन दिखाना है) · Cross-device क्लिक tracking · Offline marketing channel integration

Non-functional requirements

01हमें किस peak क्लिक rate के लिए design करना चाहिए?

Peak 10K क्लिक प्रति सेकंड, बिना किसी नुकसान के। क्लिक data ही billing data है, इसलिए pipeline इस तरह बनी है कि एक भी क्लिक कभी न गिरे।

02Advertiser dashboards को कितनी तेज़ जवाब देना चाहिए?

Query किसी भी time range पर एक सेकंड से कम में जवाब दे।

03संख्याओं को कितना fresh होना चाहिए?

Near-real-time: एक क्लिक उसके होने के लगभग एक मिनट के भीतर queryable होना चाहिए।

04ये संख्याएँ सीधे billing में जाती हैं न — यानी over-counting कभी स्वीकार्य नहीं?

नहीं — duplicates और retries कभी संख्या नहीं बढ़ा सकते; ये billing-स्तर के आँकड़े हैं।

05संख्याएँ कितनी सटीक होनी चाहिए — क्या बाद में सुधर जाने वाला थोड़ा-सा अंतर स्वीकार्य है?

शुरुआती मिनटों में छोटी अस्थायी त्रुटि सहनीय है, पर billing की संख्याएँ बिल्कुल सटीक होनी चाहिए और एक दिन के भीतर converge होनी चाहिए।

पूछते रहिए — interview एक बातचीत है

असली interview एक साफ list से कहीं गहरा probe करते हैं. ये scope सवाल उन्हें अलग करते हैं जो problem को कुरेदते हैं बनाम जो रटते हैं.

  • Minute-स्तर का data कितने समय तक queryable रहना चाहिए — 90 दिन? दो साल?
  • Bot और fraud क्लिक scope में हैं, या upstream पर ही filter हो जाते हैं?
  • Advertiser reports के लिए "एक दिन" किस timezone से तय होता है?
  • Advertiser को प्रति मिनट unique users चाहिए, या सिर्फ़ click counts?
  • एक क्लिक कितनी देर से आकर भी गिना जा सकता है?
02

वे numbers जो architecture निर्णय मजबूर करते हैं

हर estimate को एक दबाव मानिए जो किसी component को justify करता है: cache, queue, partition, replica, worker pool, या fallback path.

01

दैनिक event volume

Peak 10K क्लिक/s, ~100M क्लिक/दिन100M events × ~100 B ≈ 10 GB/day raw

Raw events को data lake में हमेशा के लिए रखना सस्ता है — यही daily reconciliation को संभव बनाता है।

02

Aggregate row count

मान लें ~10M active विज्ञापन × 1 row/minute10M विज्ञापन × एक दिन के 1,440 मिनट (24 h × 60 min) ≈ 14B rows/day worst case — पर सिर्फ़ क्लिक वाले विज्ञापन ही rows देते हैं, वास्तव में ≪ 1%

विरल minute rows OLAP store को इतना छोटा रखती हैं कि sub-second range scans हो सकें।

03

Dedup cache size

मान लें एक Impression ID ~1-घंटे की क्लिक window के लिए valid रहता है10K/s × 3,600 s × ~50 B ≈ 1.8 GB

पूरी dedup window एक Redis cluster में आराम से आ जाती है।

04

Stream processor मरने पर loss window

Flink प्रति minute-window एक बार checkpoint करता हैcrash → last checkpoint से replay ≈ अधिकतम 1 मिनट दोबारा गणना

Kafka retention (दिन) और checkpoints का मतलब है कि processor crash दोबारा गणना करता है, कभी नहीं खोता।

05

Raw events क्यों न query करें

Raw click table vs 30 दिन पर एक advertiser dashboard queryraw table हर महीने 3B rows बढ़ती है; minute granularity पर per-ad indexed slice भी हर query में लाखों rows scan करती है — sub-second से कहीं दूर

यहाँ pre-aggregation कोई optimization नहीं है — यही design है।

निर्णय उदाहरण

Numbers

एक सेकंड में दस हज़ार क्लिक यानी पैसा अंदर आ रहा है: हर खोया क्लिक बिना bill किया खर्च है, और हर double-counted क्लिक एक नाराज़ advertiser।

मेरी पसंद

क्लिक को redirect hop पर रिकॉर्ड करो और किसी और चीज़ से पहले उसे एक टिकाऊ stream (Kafka) में लिखो। फिर एक stream processor उसे लगातार एक-मिनट windows में aggregate करता है और नतीजों को उस OLAP store में flush करता है जिसे dashboards query करते हैं। हर दिखाया गया विज्ञापन एक signed impression ID रखता है, और एक Redis check duplicates गिरा देता है। दिन में एक बार, एक batch job lake से raw events दोबारा पढ़कर streamed संख्याओं को correct करता है।

बचें

जो मैं नहीं करूँगा: raw clicks को एक database में रखकर हर dashboard query पर GROUP BY चलाना। प्रति 30-दिन query तीन अरब rows इसे मार देती हैं। मैं stream को सिर्फ़ ad ID से partition भी नहीं करूँगा, क्योंकि एक viral विज्ञापन अकेले एक ही partition को पिघला देता है। इलाज सीधा है: hot ad IDs में एक random suffix जोड़ो, उन्हें N partitions पर फैलाओ, और aggregates लिखते समय suffix हटा दो। पूरी समस्या गलत partition key चुनने से आती है।

कब बदलें

अगर advertiser 5-मिनट freshness स्वीकार करते हैं, तो मैं streaming layer पूरी तरह हटा दूँगा और micro-batches चलाऊँगा — आधे moving parts, वही accuracy, बस धीमी।

03

Architecture path

पहले एक पूरी तस्वीर, फिर हर path को अपना अलग diagram — write path और read path अलग traffic ढोते हैं और अलग components justify करते हैं.

पूरी तस्वीर

Overview — हर component

ClientClick IngestionAPIKafka (eventlog)Stream ProcessorOLAP StoreDedup Cache(Redis)impression देखा गया?Data Lake (rawevents)reconciliation के लिए archiveDaily BatchReconcilerसंख्याएँ correct करता है
  • Dedup cache से पहले stream में लिखें — cache खोना कभी क्लिक खोना नहीं बनना चाहिए।
  • Dashed arrows real-time path से बाहर हैं: archiving और daily correction।
  • Daily batch raw events दोबारा पढ़ता है और बहके हुए streamed आँकड़ों को overwrite करता है।

Path 1

Click path — पहले record, फिर redirect

ClientClick IngestionAPIKafka (eventlog)Stream ProcessorOLAP Store
  • क्लिक के Kafka में सुरक्षित लिखते ही उपयोगकर्ता redirect (302) हो जाता है — उसे किसी गिनती का इंतज़ार नहीं करना पड़ता।
  • गिनती redirect के पीछे होती है: stream processor क्लिकों को per-minute rows में समेटकर OLAP store में लिखता है।
  • एक क्लिक लगभग एक मिनट में dashboards पर दिखता है — यही requirements में किया गया freshness वादा है।

Path 2

Query path — dashboards सिर्फ़ aggregates पढ़ते हैं

AdvertiserDashboardMetrics APIOLAP StoreMinuteAggregaterows
  • Dashboards कभी raw click events नहीं छूते — वे सिर्फ़ pre-aggregated minute rows पढ़ते हैं।
  • इसीलिए कोई भी time range एक सेकंड से कम में जवाब देती है: भारी काम write के समय ही हो चुका है।
04

API और data model

optimize करने से पहले contract को inspectable बनाइए: endpoints, entities, ownership, retries, और state.

GET/ads/{ad_id}/click?impression_id=

res302 Location: advertiser_url

Redirect hop हर प्रयास को टिकाऊ रूप से रिकॉर्ड करता है, फिर stream processor किसी भी billing aggregate या sink write से पहले impression_id द्वारा deduplicate करता है। एक cache duplicate checks तेज़ कर सकता है, पर billing की correctness cache loss और replay से बचकर टिकनी चाहिए।

GET/metrics?ad_id&from&to&granularity=1m

res200 [{ minute, clicks, unique_users }]

OLAP store से serve, कभी raw events से नहीं — अरबों rows पर GROUP BY वही है जिससे बचने के लिए यह design मौजूद है।

Core entities

ClickEvent

impression_id (PK) · ad_id · user_id · clicked_at

Impression ID तब बनता है जब विज्ञापन दिखाया जाता है और HMAC-signed होता है, इसलिए क्लिक forge या replay नहीं किए जा सकते।

MinuteAggregate

ad_id · minute · clicks · unique_users

OLAP store यही serve करता है; प्रति विज्ञापन प्रति मिनट एक row।

05

Deep dive दिशाएँ

interview के आखिरी एक-तिहाई के लिए एक lane चुनें. हर lane आपको topic, वह interviewer सवाल जिसका जवाब देना है, और बचने वाला failure mode देती है.

Focus

वही क्लिक, दो बार

Ask

एक उपयोगकर्ता double-click करता है, या एक retry चलता है। गिनती एक पर कैसे टिकती है?

Answer

हर दिखाए विज्ञापन में signed impression ID है: dedup cache क्लिक window के भीतर के दोहराव गिरा देता है, और minute upsert उसी ID पर idempotent है — retry कभी दूसरी गिनती नहीं जोड़ सकता।

बचें

user+ad पर dedup करना — retargeting वैध रूप से वही विज्ञापन उसी उपयोगकर्ता को दोबारा दिखाती है।

Focus

एक विज्ञापन viral हो जाता है

Ask

एक ही विज्ञापन अचानक सभी क्लिकों का आधा ले लेता है। कौन-सा component सबसे पहले अपनी सीमा पर पहुँचता है, और आप load कैसे फैलाते हैं?

Answer

Hot key को salt करें — ad_id को ad_id#0..N में बाँटें ताकि load कई partitions पर फैले, फिर एक छोटा merge step आंशिक गिनतियों को एक ही minute row में जोड़ देता है।

बचें

Stream को सिर्फ़ ad ID से partition करना — एक viral विज्ञापन हर event को एक ही partition में भेज देता है और hot key बन जाती है।

Focus

Stream processor crash हो जाता है

Ask

Flink window के बीच मर जाता है। कितने क्लिक खोते हैं, और आपको कैसे पता चलता है?

Answer

कुछ नहीं खोता: Kafka raw events रखता है, processor आख़िरी checkpoint से restart होकर ज़्यादा-से-ज़्यादा एक window दोबारा गिनता है, और idempotent upserts दोहरी गिनती की जगह overwrite करते हैं।

बचें

Stream को source of truth मानना — Kafka retention और checkpoints का मतलब replay है, loss नहीं।

Focus

एक batch layer रखें ही क्यों

Ask

Streaming पहले से real time में aggregate करता है — daily batch job क्या जोड़ता है?

Answer

Streamed संख्याएँ बहकती हैं — late events, crash, bug। दिन में एक बार batch raw events दोबारा पढ़कर हर recomputed मिनट overwrite करता है: stream ताज़गी देता है, batch बिल की गारंटी।

बचें

Reconciliation छोड़ना — billing-grade accuracy एक best-effort stream पर नहीं टिक सकती।

Focus

एक क्लिक देर से आता है

Ask

एक event अपने क्लिक के 5 मिनट बाद आता है। यह किस मिनट में गिना जाता है, और windows कितनी देर इंतज़ार करती हैं?

Answer

क्लिक के event time से गिनें, arrival time से नहीं: windows सीमित lateness (कुछ मिनट) तक रुकती हैं, उससे भी देर वालों को daily reconciliation समेट लेता है।

बचें

event-time vs processing-time को नज़रअंदाज़ करना — arrival time से गिनना चुपके से पैसा मिनटों के बीच खिसका देता है।

अभ्यास के लिए तैयार?

विज्ञापन क्लिक एग्रीगेटर को ज़ोर से समझाइए और अपनी व्याख्या पर AI scoring पाइए.

इसे AI के साथ अभ्यास करें →