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

Tinder

Tinder डिज़ाइन करें। इसमें Swipe ingestion as a high-volume, append-only event write path (like/pass events) decoupled from match detection, Match detection: checking whether A likes B AND B likes A,...

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मेरे stack में कौन दिखेगा यह क्या तय करता है — preferences, distance, या दोनों?

उपयोगकर्ता preferences (आयु सीमा, रुचियाँ) और एक अधिकतम distance सेट करते हैं; stack में केवल वे candidates होते हैं जो दोनों को संतुष्ट करते हैं।

02क्या swiping एक-एक करके है, और क्या कोई profile कभी वापस आ सकता है?

उपयोगकर्ता एक बार में एक profile पर yes/no swipe करते हैं, और swipe किया गया profile फिर कभी नहीं आता — दोहराए गए profiles टूटे हुए जैसे लगते हैं।

03आपसी yes के पल में क्या होता है?

दोनों users को match notification तुरंत मिलती है — उसी पल जब दूसरी yes उतरती है, मिनटों बाद नहीं।

04क्या उपयोगकर्ता एक left swipe को undo कर सकता है (rewind)?

एक छोटी window के भीतर, हाँ — और rewound profile stack में दोबारा दिख सकता है।

05Unmatching क्या करती है?

Unmatch match को हटाता है और chat को एक ही action में बंद करता है — एक आधा-रद्द match (chat ज़िंदा, match गया) एक trust bug है।

06एक उपयोगकर्ता session के बीच में preferences बदलता है - उनके deck का क्या होता है?

New preferences तुरंत लागू हों — दिखाया जाने वाला अगला ही profile update किए गए filters को संतुष्ट करे, पुराने को नहीं।

Scope से बाहरPhoto upload pipeline · Match के बाद messaging · Premium features (super swipes, boosts)

Non-functional requirements

01अगर दो लोग लगभग एक ही पल एक-दूसरे पर yes swipe करें, तो क्या ठीक एक match की गारंटी है — कभी zero नहीं, कभी दो नहीं?

ठीक एक match, तुरंत detected — कभी zero नहीं, कभी दो नहीं, timing चाहे कितनी भी नज़दीक हो।

02हम किस swipe volume के लिए size कर रहे हैं?

20M daily active users (DAU) × ~100 swipes ≈ 2B swipes/day — औसतन लगभग 23K swipes प्रति सेकंड।

03Stack को कितनी तेज़ी से दिखना चाहिए?

300 ms से नीचे।

04"कभी दो बार न दिखाओ" नियम कितना कठोर है?

कड़ा: यह sessions, devices, और reinstalls के आर-पार बना रहे — एक profile दो बार दिखाना एक candidate को चुपचाप skip कर देने से बुरा है।

05दूसरे उपयोगकर्ता कभी क्या location data देख सकते हैं?

केवल एक मोटा distance bucket ("~5 km दूर") — raw lat/lng किसी भी payload में backend नहीं छोड़ता।

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

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

  • Swipe history कितने समय रहनी चाहिए — हमेशा के लिए, या सालों पुरानी swipes expire हो सकती हैं?
  • क्या bot accounts और fake-profile swipes scope में हैं, या एक upstream trust-and-safety system उन्हें filter करता है?
  • अगर कोई किसी user को block या report करे, तो क्या दोनों को एक-दूसरे के stacks से तुरंत गायब होना होगा?
  • क्या कोई markets data-residency नियम थोपते हैं — क्या किसी user का location data in-region रहना ही होगा?
  • क्या super-likes / who-liked-me दायरे में हैं? वे read patterns बदल देते हैं।
02

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

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

01

Swipe लिखने की दर

20M daily active users (DAU) × ~100 swipes/day2B ÷ 86,400 s ≈ 23K swipes/s औसत, शामों में ×3-5 ≈ 100K/s peak

Swipes को एक write-optimized store चाहिए; इस दर पर mutual check प्रति swipe O(1) रहना चाहिए।

02

Seen-profile memory

मान लें एक भारी उपयोगकर्ता जीवनभर में ~50K profiles swipe करता है1% false positives पर Bloom filter ≈ 10 bits/entry → 50K × 10 b ≈ प्रति उपयोगकर्ता 62 KB

पूरा "कभी दो बार न दिखाओ" गार्ड प्रति उपयोगकर्ता kilobytes में आ जाता है — सटीक swipe इतिहास disk पर रहता है।

03

Deck precompute लागत

मान लें प्रति सक्रिय उपयोगकर्ता ~200 candidates का deck, कम पड़ने पर refresh20M users × 200 IDs × 8 B ≈ 32 GB

हर सक्रिय उपयोगकर्ता के लिए precomputed decks एक cache tier में आ जाते हैं — यही <300 ms को संभव बनाता है।

04

Live query क्यों नहीं

एक घना शहर एक max-distance circle के अंदर 20M DAU का करीब 1% रख सकता है — करीब 200K users। हर एक को अब भी geo, age, preference, और not-seen filtering चाहिए।200K candidates × filters intersect करने और seen list check करने के लिए हर एक पर ~1-2 µs ≈ प्रति request 200-400 ms — ranking शुरू होने से पहले ही पूरा 300 ms budget जल गया

Feed budget request path पर live query चलाने को खारिज कर देता है। इसके बजाय, deck को precompute करो और background में उसे top up करते रहो।

05

Match check लागत

हर yes-swipe reverse direction check करता हैप्रति swipe 1 atomic read-modify-write ≈ memory में sub-ms

जोड़ी की swipe state को साथ (एक key) रखना ही check को एक operation बनाए रखता है।

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

Numbers

peak पर एक लाख swipes प्रति सेकंड। जो एक पल गलत नहीं हो सकता वह है दो लोगों का एक ही समय पर एक-दूसरे को हाँ कहना।

मेरी पसंद

मैं हर जोड़ी की swipe state को एक key के नीचे रखूँगा — दोनों user IDs, छोटा पहले। फिर मैं swipe record करता हूँ और उल्टी swipe check करता हूँ, एक ही atomic operation में। Redis में एक Lua script यह read-modify-write एक ही step में करता है, और उसके पीछे टिकाऊ copy swipe store में लिखी जाती है। Decks हर user के लिए precompute होते हैं और एक background geo query से top up होते हैं। हर user के देखे गए profiles एक Bloom filter में रहते हैं, इसलिए "दोबारा कभी न दिखाओ" की कीमत kilobytes है, एक history scan नहीं।

बचें

जो मैं नहीं करूँगा: swipe record करना और उल्टी swipe check करना दो अलग steps में। दो एक साथ हुई yes-swipes हर एक दूसरे को चूक जाती हैं, और match कभी fire नहीं होता। वह check-then-act का अंतराल वही race है जो concert seats को दो बार बेच देता है — check और write एक ही operation होने चाहिए। मैं feed को हर request पर एक live geo query के रूप में भी नहीं बनाऊँगा, क्योंकि वह पूरा 300 ms budget index lookups पर जला देता है।

कब बदलें

अगर Redis bottleneck बन जाए, या cluster failover बहुत जटिल हो जाए, तो मैं atomicity को storage layer में ले जाऊँगा। एक compound partition key (smaller_id:larger_id) दोनों swipes को एक ही partition में उतार देता है। वहाँ, एक lightweight transaction उस जोड़ी को cover करती है — database का अपना compare-and-set, Redis से धीमा पर built-in। यह प्रति swipe ज़्यादा खर्चीला है, पर एक चलता-फिरता system बचा देता है।

03

Architecture path

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

पूरी तस्वीर

Overview — हर component

ClientAPI GatewaySwipe ServicePair State(Redis, atomic)Swipe Store(durable)MatchNotificationsआपसी yes → दोनों उपयोगकर्ताDeck Service +Cacheprecomputed feedBloom Filters(seen)कभी दो बार न दिखाओ

Swipe path consistency-critical रीढ़ है; feed path read-optimized और precomputed है। Dashed = durable swipes से asynchronously बनाए रखा गया, cache loss के बाद फिर बनाया जा सकने वाला।

Path 1

Swipe path — record करो और atomically match करो

ClientSwipe ServicePair Key (Lua,one op)Swipe StoreMatchNotification

एक atomic operation swipe record करता है और उल्टी swipe check करता है। टिकाऊ write उसके बाद आती है। अगर एक Redis node खो जाए, तो वह टिकाऊ store से replay करता है और ज़्यादा से ज़्यादा आख़िरी कुछ बिना flush की swipes खोता है — swipe-path speed के लिए एक स्वीकार्य trade।

Path 2

Feed path — precomputed deck, top up किया गया

ClientDeck CacheDeck ServiceGeo + PreferenceQueryBloom Filter(exclude seen)

Request path केवल deck पढ़ता है। जब यह कम पड़ता है, background query इसे फिर भरती है, Bloom filter के ज़रिए seen profiles को बाहर रखते हुए — false positives एक candidate छोड़ते हैं, किसी को दोहराते कभी नहीं।

04

API और data model

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

POST/profile

req{ age_min, age_max, distance_km, interested_in }

res200 profile

पहचान session token से। Preference बदलाव precomputed deck को invalidate करते हैं।

GET/feed

res200 User[] (next slice of the deck)

Precomputed deck serve करता है; जब यह कम पड़ता है, एक ताज़ा geo+preference query इसे top up करती है। Location query parameters से नहीं, session context से आती है।

POST/swipe/{target_user_id}

req{ decision: yes | no }

res200 { matched: boolean } — matched:true fires both notifications

वह atomic कदम: swipe record करो और reverse swipe को एक ही operation में check करो।

Core entities

User

user_id (PK) · profile · preferences · geo_cell (coarse)

Location matching के लिए एक मोटे geo cell के रूप में store होती है; सटीक coordinates कभी दूसरे clients को serve नहीं किए जाते।

Swipe

swiping_user · target_user · decision: yes/no · swiped_at

Swipe store में durably लिखा जाता है; साथ ही swiper के seen profiles के Bloom filter में मोड़ा जाता है।

Match

match_id (PK) · user_a · user_b · matched_at

05

Deep dive दिशाएँ

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

Focus

एक साथ yes

Ask

दो उपयोगकर्ता एक ही 10 ms में एक-दूसरे पर yes swipe करते हैं। वे सटीक operations चलाओ जो एक match पैदा करें, शून्य नहीं।

Answer

इसे एक atomic operation बनाओ। दोनों users का swipe state एक ही key के नीचे store करो, दोनों IDs को छोटा पहले करके sort करके। Swipe record करो और reverse swipe के लिए check करो — एक ही Redis Lua script में। दूसरा swipe हमेशा पहले को देख लेता है, तो ठीक एक ही match fire होता है।

बचें

दो कदमों में read-then-write — दोनों swipes एक-दूसरे को चूक जाती हैं और match चुपचाप कभी नहीं होता।

Focus

कभी दो बार न दिखाओ

Ask

आप इतिहास scan किए बिना हर deck refill से 50,000 पहले swipe किए profiles को कैसे बाहर रखते हैं?

Answer

हर user के लिए एक Bloom filter इस्तेमाल करो — हर profile का जिसे उन्होंने swipe किया। 50K entries पर यह करीब 62 KB है। हर deck candidate को उसके ख़िलाफ़ screen करो; एक false positive बस एक candidate छोड़ देता है और किसी को कभी दोहराता नहीं। Bloom filter unlearn नहीं कर सकता, तो आख़िरी कुछ swipes को एक छोटे exact buffer में रखो — यही rewind को चलाता है।

बचें

Bloom false positives को एक bug मानना — एक candidate छोड़ना डिज़ाइन की गई लागत है; एक को दोहराना विफलता है।

Focus

Deck सूख जाता है

Ask

एक सक्रिय उपयोगकर्ता अपने पूरे precomputed deck को swipe कर जाता है। इसे क्या फिर भरता है, यह कितना fresh है, और वे कितनी latency देखते हैं?

Answer

हर request का जवाब precomputed deck cache से दो। Refills एक low-water mark पर asynchronously चलते हैं, तो एक background geo-and-preference query 200-candidate deck को दोबारा बना देती है — user के नीचे पहुँचने से पहले। यही precompute एक live multi-filter query को 300 ms path से बाहर रखता है। एक preference change deck को गिरा देता है और उसी तरह refill करता है।

बचें

खाली-deck request पर synchronously refill करना — query शुरू होने से पहले ही 300 ms budget चला जाता है।

Focus

Location को लीक किए बिना

Ask

Matching को distance चाहिए, उपयोगकर्ताओं को कभी coordinates नहीं देखने चाहिए। precision कहाँ गिराई जाती है, और API वास्तव में क्या लौटाता है?

Answer

Precise coordinates सिर्फ़ server-side रखो, candidate selection के लिए। Backend distance compute करता है और उसे किसी response में जाने से पहले एक coarse bucket में round कर देता है, जैसे "~5 km दूर"। कोई भी payload किसी field में lat/lng नहीं ले जाता। Client पर rounding करना दिखावा है — payload खुद ही leak है।

बचें

Clients को raw lat/lng भेजना और UI में round करना — payload ही लीक है।

Focus

सब एक ही व्यक्ति को swipe करते हैं

Ask

एक बहुत लोकप्रिय profile लाखों decks में दिखता है। पहले क्या hot-spot होता है, और आप exposure कैसे संतुलित रखते हैं?

Answer

Profile की pair keys और swipe partitions सबसे पहले hot-spot होती हैं, तो उस state को shard या replicate करो। फिर profile को एक exposure budget दो: एक cap कि वह एक साथ कितने live decks घेर सकता है, जो swipes के उसे खाली करते ही refill होता रहे। इस तरह एक popular profile हर पास वाले deck को नहीं भर सकता और बाकी सबको views से वंचित नहीं कर सकता।

बचें

Exposure skew को नज़रअंदाज़ करना — बिना caps के, लोकप्रिय profiles हर deck पर हावी हो जाते हैं और engagement ढह जाता है।

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

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

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