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

टिकटिंग सिस्टम

टिकटिंग सिस्टम डिज़ाइन करें। इसमें Seat inventory model and seat-map representation for a venue/event, including seat status transitions, Reservation hold with TTL: reserve then confirm two-phase...

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उपयोगकर्ताओं को क्या करना है — 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

Non-functional requirements

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 एक बातचीत है

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

  • Seat map वाली reserved seating, या capacity counter वाली general admission — या दोनों?
  • क्या refunds या cancellations seats वापस बिक्री पर डालते हैं, या यह scope से बाहर है?
  • क्या प्रति event प्रति user कोई ticket limit है जिसे हमें enforce करना होगा?
  • क्या हम card details खुद संभालते हैं, या एक payment provider को सौंप देते हैं — क्या PCI compliance हम पर आती है?
  • क्या bot और scalper mitigation scope में है?
02

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

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

01

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 तक कौन पहुँचता भी है।

02

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 पर कोई असर नहीं पड़ता।

03

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 नहीं देखता।

04

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 कर देता है।

05

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 पर रखें।

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

Numbers

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 रखूँगा और शून्य पर पहुँचते ही बेचना बंद कर दूँगा।

03

Architecture path

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

पूरी तस्वीर

Overview — हर component

ClientAdmissionControlBooking ServiceHold Store (TTL)Seat InventoryDBPayment Serviceidempotent confirmSeat-Map Cache +Searchbrowse / search reads

Booking रीढ़ है; browse और search कभी seat inventory को नहीं छूते (dashed = read side, booking hot path से बाहर)। एक expired hold seats अपने-आप लौटा देता है।

Path 1

Booking path — reserve, फिर confirm

ClientAdmissionControlBooking ServiceHold Store (TTL)Seat InventoryDBPayment Service
  • Reserve एक countdown (TTL) के साथ hold लगाता है — अगर buyer कभी pay न करे, तो hold expire हो जाता है और seat खुद वापस बिक्री पर आ जाता है।
  • Confirm payment charge करता है और held seats को एक atomic step में sold में पलट देता है; confirm को retry करना कभी दो बार charge या book नहीं करता।
  • "क्या यह seat free है?" और "इसे held mark करो" एक ही single step होना चाहिए — एक row lock, या एक update जो तभी succeed हो जब seat नीचे से बदली न हो (compare-and-set)।
  • अगर वे दो अलग steps होते, तो दो buyers उनके बीच के gap में दोनों check pass कर सकते थे — और seat दो बार बिक जाती।

Path 2

Browse path — search और seat map (read-heavy)

ClientCDN / EdgeEvent + SearchServiceSeat-Map CacheDatabase

Event pages पहले से render और CDN-cached होते हैं, इसलिए एक flash sale static content के लिए कभी app servers तक नहीं पहुँचती। Availability कुछ सेकंड पीछे रह सकती है। सच booking transaction पर ही enforce होता है।

04

API और data model

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

Event

event_id (PK) · venue_id · performer · starts_at · on_sale_at

Ticket

ticket_id (PK) · event_id · section/row/seat · price · status: available/held/booked · version

status + version optimistic concurrency चलाते हैं; event_id से partition करें ताकि एक on-sale दूसरे events को degrade न कर सके।

Booking

booking_id (PK) · user_id · ticket_ids · total · status: pending/confirmed/failed · idempotency_key

User

user_id (PK) · email · created_at

05

Deep dive दिशाएँ

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

Focus

Seat states

Ask

एक seat को available → held → sold से गुज़ारें। हर state को ठीक-ठीक क्या बदलता है, और क्या दो लोग कभी एक ही seat hold कर सकते हैं?

Answer

एक 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 कर देते हैं।

Focus

पहले reserve, बाद में confirm

Ask

Payment से पहले seat क्यों hold करें, और अगर payment कभी पूरा न हो तो उसका क्या होता है?

Answer

पहले seat hold करो ताकि जब तक buyer card details type करे, वह उसी की रहे। अगर तुमने reserve के वक़्त ही उसे sold मार दिया, तो हर failed या छोड़ा गया payment एक ऐसी seat फँसा देता जो बेची नहीं जा सकती। जब payment कभी पूरा नहीं होता, TTL hold को expire कर देता है और seat अपने आप वापस बिक्री पर आ जाती है — किसी cleanup job की ज़रूरत नहीं।

बचें

Reserve के समय seat को sold mark करना — तब एक failed payment उसे बिकाऊ नहीं रहने देता।

Focus

Double-sell रोकना

Ask

Row lock, version check (CAS), या atomic counter — हर एक दो buyers को एक ही seat जीतने से कैसे रोकता है, और contention में हर एक की क्या कीमत है?

Answer

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 होते हैं।

Focus

On-sale spike से बचना

Ask

10M लोग एक on-sale पर टूट पड़ते हैं। आप उन्हें ज़्यादातर को error देकर बाहर करने के बजाय निष्पक्ष रूप से कैसे इंतज़ार कराते हैं?

Answer

पूरे 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 उसी की रक्षा के लिए है।

Focus

ठीक एक बार payment

Ask

Confirm request दो बार आती है — एक retry या एक double click। आप कैसे पक्का करते हैं कि card एक बार charge हो और seat एक बार बिके?

Answer

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 पाइए.

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