01उपयोगकर्ताओं को क्या करना है — events browse और search करना, या यह सिर्फ़ booking है?
उपयोगकर्ता किसी event को उसके venue seat map और near-real-time availability के साथ देख सकते हैं, और events को keyword, date और location से search कर सकते हैं।
मुफ़्त पूरी गाइड
टिकटिंग सिस्टम डिज़ाइन करें। इसमें Seat inventory model and seat-map representation for a venue/event, including seat status transitions, Reservation hold with TTL: reserve then confirm two-phase...
Interview की लय संक्षिप्त रहती है, ताकि page असली design निर्णयों पर ध्यान लगा सके.
सिर्फ requirements मत बताइए — पूछिए। हर card एक design constraint को उस clarification सवाल से जोड़ता है जो आप architecture बनाने से पहले बोल सकते हैं.
01उपयोगकर्ताओं को क्या करना है — events browse और search करना, या यह सिर्फ़ booking है?
उपयोगकर्ता किसी event को उसके venue seat map और near-real-time availability के साथ देख सकते हैं, और events को keyword, date और location से search कर सकते हैं।
02जब उपयोगकर्ता seats चुनता है, तो क्या payment के दौरान उसे एक temporary hold मिलता है?
Users seats चुन सकते हैं और एक short-lived hold (5-10 मिनट) पा सकते हैं। वे पहले reserve करते हैं, फिर payment से confirm करते हैं। जो hold कभी confirm नहीं होता वह अपने-आप release हो जाता है।
03वह एक guarantee क्या है जिसे हम कभी नहीं तोड़ सकते?
एक booking final होती है: हर seat ठीक एक बार बिकती है — कभी double-booking नहीं, flash on-sale के दौरान भी नहीं।
04Seat-map selection, best-available allocation, या दोनों?
दोनों। Reserved venues के लिए map selection, प्लस best-available। Best-available भी विशिष्ट seats पर atomic holds लेता है, कभी एक धुँधली गिनती पर नहीं।
05क्या कोई buyer checkout के बीच में मौजूदा hold में seats जोड़ सकता है?
हाँ, जब तक hold अभी ज़िंदा है। जोड़ी गई seats अपने खुद के holds लेती हैं, जो उसी booking में atomically जुड़ते हैं। वे सब एक साथ confirm होती हैं, या यह जोड़ साफ़-साफ़ fail हो जाती है।
06Sold out — क्या हमें waitlist चाहिए?
पहले दिन scope से बाहर — पर waitlist एक संभावित follow-up है, इसलिए पहले-दिन के choices एक जोड़ना दर्दनाक न बना दें।
Scope से बाहरHot events के लिए dynamic pricing · Events बनाने के लिए admin और event-coordinator tooling · पिछली bookings देखना, ticket transfer, और resale
01हमें strong consistency कहाँ चाहिए, और data कहाँ stale रह सकता है?
Booking को strong consistency चाहिए, ताकि एक seat दो बार न बिके। Browse और search को सिर्फ़ availability चाहिए। Seat map असल हालत से कुछ सेकंड पीछे रह सकता है।
02Peak पर एक flash on-sale कैसा दिखता है?
एक hot event on-sale के पल पर ~10M users खींच सकता है। System को उस spike को सोखना है। Users को fail करने की बजाय उन्हें fairly इंतज़ार कराना ठीक है।
03Browsing और search कितना तेज़ महसूस होना चाहिए?
Search ~500 ms से नीचे; seat-map views एक rush के दौरान भी instant महसूस हों। कुल मिलाकर read-heavy, लगभग 100:1 पर।
04एक hold कितनी देर चल सकता है, और expiry पर क्या होता है?
Holds छोटे होते हैं (5-10 मिनट) TTL auto-release के साथ। छोड़े गए checkouts बिना manual सफ़ाई के seats लौटा देते हैं। Holds को payment-provider की latency से भी ज़्यादा जीना होगा।
05अगर एक confirm दो बार आए — एक double click, या payment provider का webhook retry — तो क्या charge और sale फिर भी केवल एक बार ही होनी चाहिए?
Retries और duplicate payment webhooks कभी double-charge या double-book न करें — दो बार confirm करने का वही असर हो जो एक बार confirm करने का।
असली interview एक साफ list से कहीं गहरा probe करते हैं. ये scope सवाल उन्हें अलग करते हैं जो problem को कुरेदते हैं बनाम जो रटते हैं.
हर estimate को एक दबाव मानिए जो किसी component को justify करता है: cache, queue, partition, replica, worker pool, या fallback path.
On-sale पर contention
~10M उपयोगकर्ता (on-sale requirement से) एक on-sale पल में मान लिए गए ~50K seats के लिए contend करते हैं10,000,000 ÷ 50,000 ≈ 200 users प्रति seat
लगभग सबको waiting room में ही कतार में रोक लेना होगा — admission control तय करता है कि booking तक कौन पहुँचता भी है।
Reserve का write burst
On-sale का पहला मिनट: हर admitted user एक hold का प्रयास करता हैadmit 50K users/min ≈ एक event partition पर 800 reserve attempts/s
Per-event partitioning और छोटी atomic transitions hot partition को ज़िंदा रखती हैं। बाकी events पर कोई असर नहीं पड़ता।
Browse read skew
~100:1 पर read-heavy — seat-map polling हावी है800 writes/s × 100 ≈ peak पर 80K seat-map reads/s
Views को cache/CDN से कुछ seconds की staleness के साथ परोसें — inventory database कभी browse traffic नहीं देखता।
Hold TTL बनाम payment latency
External payment confirm का p95 seconds में है; users मिनटों तक forms भरते हैंTTL 5-10 min ≫ payment p95 ~3-10 s
उदार TTL holds को payment के बीच expire होने से बचाता है; expiry बिना cleanup jobs के छोड़ी गई seats auto-release कर देता है।
Search latency budget
Search target < 500 ms end-to-endinverted-index query ~50-100 ms + ranking + network ≈ 500 ms से काफ़ी कम
एक full-text index (LIKE scans नहीं) ज़रूरी है; दोहराई गई queries cache करें और non-personalized results CDN पर रखें।
निर्णय उदाहरण
on-sale की कल्पना करो: ~10M लोग ~50K seats चाहते हैं — करीब 200 लोग प्रति seat। लड़ाई हर seat की state पर है, इसलिए एक seat पर writes एक-एक करके होने चाहिए। इस बीच, जो बस browse कर रहे हैं वे सब cache से serve होते हैं।
मैं तीन चीज़ें करूँगा। पहला, सबको एक waiting room में रखूँ और उन्हें एक नियंत्रित दर पर booking flow में आने दूँ, ताकि seat database को हमेशा उतना ही traffic मिले जितना वह झेल सके। दूसरा, जब user seats चुने, तो उन्हें 5-10 मिनट के लिए hold करूँ — उस window में payment हो जाए वरना seats अपने-आप वापस on sale आ जाएँ। तीसरा, 'seat free है यह check करना AND उसे held mark करना' को एक अकेला atomic step बनाऊँ (एक row lock, या एक ऐसा update जो तभी सफल हो जब बीच में किसी ने seat न बदली हो), ताकि दो buyers कभी दोनों उसे न पकड़ सकें।
जो मैं नहीं करूँगा: पहले 'seat free है' पढ़ना, फिर दूसरे step के रूप में उसे held mark करना। उन दो steps के बीच के अंतराल में दूसरा buyer वही read कर सकता है — दोनों सोचते हैं वे जीत गए, और seat दो बार बिक जाती है। Check और update एक ही step होने चाहिए, और हारने वाले को एक साफ़ 'कोई आपसे पहले ले गया' जवाब मिलना चाहिए (HTTP 409), न कि एक silent failure।
अगर venue general admission हो, बिना विशिष्ट seats के और बस एक capacity number के साथ, तो per-seat locking ज़रूरत से ज़्यादा है। मैं बची हुई capacity का एक atomic counter रखूँगा और शून्य पर पहुँचते ही बेचना बंद कर दूँगा।
पहले एक पूरी तस्वीर, फिर हर path को अपना अलग diagram — write path और read path अलग traffic ढोते हैं और अलग components justify करते हैं.
पूरी तस्वीर
Booking रीढ़ है; browse और search कभी seat inventory को नहीं छूते (dashed = read side, booking hot path से बाहर)। एक expired hold seats अपने-आप लौटा देता है।
Path 1
Path 2
Event pages पहले से render और CDN-cached होते हैं, इसलिए एक flash sale static content के लिए कभी app servers तक नहीं पहुँचती। Availability कुछ सेकंड पीछे रह सकती है। सच booking transaction पर ही enforce होता है।
optimize करने से पहले contract को inspectable बनाइए: endpoints, entities, ownership, retries, और state.
GET/events/{event_id}
res200 { event, venue, seat_map, availability }
Cache/CDN-first; availability कुछ seconds पीछे रह सकती है — booking ही वह जगह है जहाँ सच्चाई enforce होती है।
GET/events/search?keyword&date&location
res200 Event[]
Inverted index (full-text) — fuzzy matches समेत 500 ms से कम।
POST/bookings
req{ event_id, ticket_ids[] }
res201 { booking_id, hold_expires_at } · 409 seat पहले से held या sold
TTL hold बनाता है: seats atomically held में बदलती हैं या पूरी request fail हो जाती है — कोई partial holds नहीं।
POST/bookings/{booking_id}/confirm
req{ payment_token, idempotency_key }
res200 confirmed · 402 payment failed (hold चलता रहता है) · 410 hold expired
प्रति booking_id idempotent: payment-provider retries और duplicate webhooks safe हैं।
Core entities
Eventevent_id (PK) · venue_id · performer · starts_at · on_sale_at
Ticketticket_id (PK) · event_id · section/row/seat · price · status: available/held/booked · version
status + version optimistic concurrency चलाते हैं; event_id से partition करें ताकि एक on-sale दूसरे events को degrade न कर सके।
Bookingbooking_id (PK) · user_id · ticket_ids · total · status: pending/confirmed/failed · idempotency_key
Useruser_id (PK) · email · created_at
interview के आखिरी एक-तिहाई के लिए एक lane चुनें. हर lane आपको topic, वह interviewer सवाल जिसका जवाब देना है, और बचने वाला failure mode देती है.
एक seat को available → held → sold से गुज़ारें। हर state को ठीक-ठीक क्या बदलता है, और क्या दो लोग कभी एक ही seat hold कर सकते हैं?
एक atomic write एक seat को available से held में पलट देता है। यह तभी सफल होता है जब seat अब भी available हो, तो दूसरा buyer बस fail हो जाता है। दो लोग एक ही seat hold नहीं कर सकते, क्योंकि check और flip एक ही step हैं। Payment के बाद confirm held को sold में बदल देता है; एक expired TTL उसे वापस available भेज देता है।
बिना TTL के holds — छोड़े गए carts seats को हमेशा के लिए lock कर देते हैं।
Payment से पहले seat क्यों hold करें, और अगर payment कभी पूरा न हो तो उसका क्या होता है?
पहले seat hold करो ताकि जब तक buyer card details type करे, वह उसी की रहे। अगर तुमने reserve के वक़्त ही उसे sold मार दिया, तो हर failed या छोड़ा गया payment एक ऐसी seat फँसा देता जो बेची नहीं जा सकती। जब payment कभी पूरा नहीं होता, TTL hold को expire कर देता है और seat अपने आप वापस बिक्री पर आ जाती है — किसी cleanup job की ज़रूरत नहीं।
Reserve के समय seat को sold mark करना — तब एक failed payment उसे बिकाऊ नहीं रहने देता।
Row lock, version check (CAS), या atomic counter — हर एक दो buyers को एक ही seat जीतने से कैसे रोकता है, और contention में हर एक की क्या कीमत है?
Reserved seating के लिए, short row locks या single-statement conditional updates इस्तेमाल करो, और admission control से contention कम करो। एक row lock buyers को serialize करता है: हमेशा सही, पर वे hot rows पर queue में लग जाते हैं। एक version check (CAS) locks छोड़ देता है, पर ~200 buyers प्रति seat पर ज़्यादातर retry करते हैं और हारते रहते हैं। एक atomic counter सिर्फ़ interchangeable seats में फिट बैठता है — general admission।
Flash sale में शुद्ध optimistic retries — ज़्यादातर buyers निष्पक्ष रूप से इंतज़ार करने के बजाय बार-बार fail होते हैं।
10M लोग एक on-sale पर टूट पड़ते हैं। आप उन्हें ज़्यादातर को error देकर बाहर करने के बजाय निष्पक्ष रूप से कैसे इंतज़ार कराते हैं?
पूरे 10M को एक waiting room में डालो और उन्हें एक controlled rate पर admit करो। एक token bucket लगभग 50K users प्रति minute booking flow में छोड़ता है, तो seat inventory को हमेशा उतना ही traffic दिखता है जितना वह झेल सके। बाकी सबको एक fair queue position मिलती है, errors के ख़िलाफ़ retry पीटने के बजाय। दूसरे events कभी उस spike को महसूस नहीं करते।
पूरे झुंड को seat inventory तक पहुँचने देना — waiting room उसी की रक्षा के लिए है।
Confirm request दो बार आती है — एक retry या एक double click। आप कैसे पक्का करते हैं कि card एक बार charge हो और seat एक बार बिके?
Confirm एक idempotency key और booking_id साथ लाता है, और service पहले attempt का outcome store कर लेती है। उसी key वाला कोई भी retry या duplicate webhook दोबारा चलने के बजाय वही stored result वापस पाता है। तो request चाहे कितनी भी बार आए, card एक बार charge होता है और seat एक बार बिकती है।
Confirm पर कोई idempotency key नहीं — एक network retry double-charge या double-sell कर देती है।
टिकटिंग सिस्टम को ज़ोर से समझाइए और अपनी व्याख्या पर AI scoring पाइए.