System Design blueprint · Entertainment ticketing
Movie & event ticket booking (BookMyShow)
Lets users pick seats, hold them briefly, pay and receive a QR e-ticket, while a waiting room shields the system during blockbuster openings. It must never sell the same seat for the same show twice, even under a massive rush.
- Steps
- 9
- Subjective questions
- 33
- Objective questions
- 33
The problem and the outcome
Problem: Popular shows draw thousands of users clicking the same seats at the same second. Without strict locking you get double bookings, stuck seats from abandoned payments, and outages at opening time.
Outcome: Each seat is held by exactly one user for a short TTL, and only a successful payment inside that window turns the hold into a confirmed booking. Expired holds free themselves, refunds are automatic and traffic spikes are absorbed by a fair queue.
Architecture
How it works, step by step
- For shows flagged as high demand, users first get a signed queue token from the waiting room, which admits them to the booking flow in controlled batches so the core services see a steady load.
- The booking service serves the seat map from a cache of seat states (available, held, booked) for the chosen show and accepts a seat selection with an idempotency key.
- For each seat it runs an atomic Redis SET NX with a TTL on key show:seat, all-or-nothing for the group (a Lua script), and records a hold row with hold_id and expires_at in the inventory DB.
- The booking service creates a payment order tied to the hold_id and amount, and the user pays via UPI, card or wallet inside the hold window shown as a countdown.
- On the signed payment webhook, the decision step checks the hold is still valid and runs a conditional update (set BOOKED where hold_id matches and status is HELD); a unique constraint on show and seat is the final guard against double booking.
- The ticket service generates a booking with a signed QR payload (booking id, show, seats, signature), stores it, and publishes BookingConfirmed so notifications deliver the e-ticket.
- When a hold TTL lapses without payment, Redis frees the key and a sweeper releases matching DB holds with expires_at in the past, returning seats to the map.
- Cancellations are checked against the show's refund policy, seats are marked free, and a refund is issued through the gateway with an idempotency key; late payments for expired holds are refunded the same way.
- At the venue, scanners verify the QR signature and mark the ticket used atomically, so a screenshot cannot be used twice.
Tech stack
- Redis (SET NX EX, Lua scripts) for seat holds
- PostgreSQL for seats, holds and bookings with unique constraints
- Kafka for booking and payment events
- Payment gateway with signed webhooks and refund APIs (e.g. Razorpay, PayU)
- Virtual waiting room at the edge (e.g. Cloudflare Waiting Room or a custom token queue)
- CDN plus cache for seat maps and show listings
- HMAC or Ed25519 signed QR codes
Key design decisions
- Use Redis locks for fast, contended holds but keep the relational DB as the source of truth with a conditional update and unique constraint, so a Redis failover cannot cause a double sale.
- Lock all seats in a selection atomically; partial holds create confusing UX and orphaned locks.
- Make the hold TTL configurable per show and slightly longer than the payment gateway's own timeout, so in-flight payments are not cut off.
- Treat payment webhooks as at-least-once: dedupe on payment id and booking idempotency key before changing seat state.
- Gate only flagged blockbuster shows through the waiting room to keep normal bookings frictionless.
Common mistakes
- Relying only on Redis TTL locks; a lock expiring during a slow payment lets a second user grab the seat unless the DB commit checks hold_id.
- Ignoring late webhooks after a hold expires, which leaves users charged without a ticket; always auto-refund or re-acquire if seats are still free.
- Using a database row lock across the whole payment window, which kills throughput on hot shows.
- Unsigned or sequential QR codes that can be forged or shared.
- Letting the seat map cache show stale availability, which causes repeated failed hold attempts and retry storms.
What to measure
- Double bookings per show (target zero)
- Hold-to-booking conversion rate and hold expiry rate
- p99 latency of seat hold requests during peak
- Charged-but-no-ticket incidents and time to auto-refund
- Waiting room admission rate and abandonment
Most-asked interview questions
Subjective questions 33
1How do you guarantee no double booking when thousands of users click the same seat?Asked almost every time
I use two layers. First, a fast contended lock: Redis SET NX with a TTL on a key per show and seat, done atomically for the whole selection with a Lua script. Only one user wins; others get an immediate seat-taken response. Second, the database is the source of truth. When payment succeeds I run a conditional update that sets the seat to BOOKED only if it is still HELD by that hold_id, and a unique constraint on show and seat in the bookings table blocks any second insert. So even if Redis fails over and loses a lock, the database refuses the duplicate, and the losing payment is refunded automatically.
2Walk me through the high-level architecture and the main services in this booking system.Asked almost every time
At the edge, a CDN and API gateway sit in front of a waiting room service that issues signed queue tokens for high-demand shows. Behind it, a catalog service serves movies, venues and shows. The booking service owns the seat map cache and seat holds. Redis keeps short-lived locks, and a relational inventory DB holds the durable seat, hold and booking state. A payment service creates gateway orders and receives signed webhooks. A ticket service creates the booking and the signed QR. An event bus carries BookingConfirmed to notifications and analytics. A sweeper releases expired holds. A venue scanning service validates QR codes. Each service owns its own data. Correctness lives in the inventory DB, and the other layers are there to absorb load.
3How would you design the data model for shows, seats, holds and bookings?Asked almost every time
A show row stores show_id, screen_id, start time, pricing and refund policy. The seat layout is defined once per screen, with seat_id, row, number and category. For each show, a show_seat table has one row per seat: show_id, seat_id, status (AVAILABLE, HELD, BOOKED), hold_id, price and version. Its primary key on (show_id, seat_id) enforces one state per seat. A hold table stores hold_id, user_id, show_id, seat list, amount, idempotency key and expires_at. The booking table stores booking_id, hold_id, payment reference, status and the QR payload. A ticket_scan table records whether each ticket is used. I partition everything by show_id, so a booking touches a single shard.
4What if the payment webhook never arrives? How do you reconcile?Asked almost every time
Webhooks can be delayed or lost, so they cannot be the only signal. A reconciliation job looks for payment orders that are still pending close to or after their hold expiry, and calls the gateway's order status API. If the payment was captured, it runs the same idempotent decision step as the webhook would. If the hold is still valid, the booking is confirmed. If not, a refund is started. The client can also trigger a status check when it returns from the payment app. A daily settlement reconciliation then compares gateway reports against bookings and refunds, to catch anything left over. All paths share one idempotent handler keyed by the payment ID.
5How do you reliably publish BookingConfirmed after the booking is saved?Asked almost every time
Writing to the database and then publishing to the broker as two separate steps can fail in between. That would leave a booking with no e-ticket sent. I use a transactional outbox: in the same DB transaction that sets seats BOOKED and inserts the booking, I insert an outbox row with the event. A relay process, or change data capture, reads the outbox and publishes to the event bus, retrying until it succeeds. That gives at-least-once delivery, so consumers like notifications must be idempotent, deduplicating on the event ID or booking ID. Users can always download the ticket from the app as well, so a slow notification never blocks access.
6What happens if a payment succeeds after the seat hold has expired?Very often asked
This is a real edge case because gateways and UPI can confirm late. The webhook handler is idempotent on payment id. It checks the hold: if expired, it tries to re-acquire the same seats with the same conditional update. If they are still free, the booking is confirmed and the user gets a ticket. If someone else took them, we mark the payment for auto-refund through the gateway refund API with an idempotency key and notify the user clearly. I also set the hold TTL slightly longer than the payment timeout shown to the user, which reduces how often this happens, and I track charged-without-ticket as a key metric.
7How would you design the waiting room for a blockbuster opening?Very often asked
The waiting room sits at the edge before the booking service. When a show is flagged as high demand, users get a signed token with a queue position, ideally assigned fairly, for example randomized among those who arrived before sale opening, then first come after that. A controller admits users in batches based on the backend's measured capacity, such as hold requests per second, and admitted users get a short-lived pass the booking service validates. The page polls cheaply from a CDN-friendly endpoint. This protects Redis and the DB from spikes, blocks bots that skip the queue, and gives users an honest position instead of errors.
8Why use Redis for seat holds at all, instead of only locking rows in the database?Very often asked
During a rush, most attempts fail because many people want the same seats. Redis answers 'is it taken?' in memory, in sub-millisecond time, without holding database connections or row locks. That keeps the inventory DB free for the much smaller number of writes that actually succeed. The TTL also gives automatic expiry with no cleanup transaction. The trade-off is that Redis is not the source of truth. Replication is asynchronous, so a failover can lose a hold. That is why the DB hold row and the conditional update with the unique key still decide the final outcome. Redis is a fast filter in front of the database, not the guarantee.
9How do you decide the length of the seat hold TTL?Very often asked
The hold has to cover realistic payment time, including UPI app switching, OTPs and bank redirects. But every extra minute keeps seats away from other buyers, which hurts conversion during a rush. I would set it from measured payment completion times, for example a high percentile of successful payments, and not guess. I would also make it configurable per show, with a shorter hold for high-demand shows. The countdown shown to the user should end slightly before the server-side expiry, so network delay does not cause disputes. If payment is still in progress, a single bounded extension can help. Then I track hold-to-booking conversion and expired-hold rates to keep tuning it.
10How do you keep the seat map cache consistent with actual inventory?Very often asked
I accept that the seat map is eventually consistent, because it is only a display. The real check happens when a hold is attempted. Every state change (hold, book, release) updates Redis, or publishes an event that updates the cached map for that show. A short TTL or version number on the map bounds how stale it can get. If a user picks a seat that looks free but is already taken, the SET NX fails, and we return a clear conflict with a refreshed map. For hot shows, pushing deltas over WebSocket or SSE cuts wasted attempts. Polling with ETags is a simpler fallback. The key point is that cache staleness costs user experience, never correctness.
11Give a back-of-envelope capacity estimate for a blockbuster opening.Very often asked
I would state my assumptions clearly rather than claim real numbers. Suppose N users arrive in the first minutes and the waiting room admits A users per second. Each admitted user makes a few seat-map reads and one or two hold attempts. So hold QPS is roughly A times attempts, and map reads are a few times that. Inventory writes are bounded by the number of seats sold, which is fixed by venue capacity, not by traffic. Queue wait is about N divided by A. A should be set from load tests, at a level where p99 latency of the booking and payment services stays within SLO. This shows why the waiting room matters: it turns an unbounded spike into a load we chose.
12What happens if the Redis primary fails and the replica that takes over has lost some holds?Very often asked
Replication is asynchronous, so a few recent SET NX writes can disappear during failover. Those seats then look free, and a second user might get a Redis hold on a seat someone else is paying for. The DB still protects us. Each hold row carries the seat's hold_id, and a second hold insert or status change on show_seat fails if the seat is already HELD by a hold that has not expired. At payment time, the conditional update matches only the correct hold_id. In the worst case, one user's payment cannot be confirmed and is refunded automatically. That is a bad experience but not a double sale. I would alert on failovers and reconcile Redis keys against DB holds afterwards.
13How do you stop people from forging, sharing or reusing waiting room tokens?Very often asked
The token is signed by the waiting room, as a JWT or similar. It contains the show or event ID, user or session ID, admission time and a short expiry. The gateway checks the signature and expiry on every booking call, so anyone without a valid token is rejected before reaching core services. Binding the token to the logged-in account, and optionally a device fingerprint, makes sharing useless. Each token gets a single-use ID or limited uses, tracked in Redis, so it cannot admit many sessions. Short expiry limits replay. Combined with per-account ticket limits, this stops one person from flooding the booking flow with copies of a single admission.
14How do you prevent a race between the sweeper releasing a hold and a payment confirming it?Very often asked
Both operations are conditional updates on the same row, so the database serializes them. The sweeper runs: set AVAILABLE where status is HELD, hold_id matches and expires_at is earlier than the database's now. The confirmation runs: set BOOKED where status is HELD, hold_id matches and the hold has not expired. Exactly one of them changes the row. If the sweeper wins, the confirmation affects zero rows and triggers a refund. I use database time rather than app server clocks to avoid skew. I also never let the sweeper free a Redis key unless it still holds that hold_id. This way the race always has a clear, safe outcome.
15How would you shard the inventory database?Very often asked
I shard by show_id, because almost every critical operation (hold, confirm, release, scan) is scoped to a single show. That keeps the transaction on one shard with no distributed transactions. Hash or range on show_id spreads load across shards. The risk is a hot shard, since one blockbuster show concentrates its writes on one shard. But a show has a fixed number of seats, so writes are bounded, and the waiting room plus Redis already filter most failed attempts. User-facing views like 'my bookings' are served from a separate store or read model indexed by user_id, fed by events. Catalog data is replicated and cached separately.
16How do you deal with bots and scalpers during a big ticket release?Very often asked
I use layered defences. At the edge, I add bot management, rate limits per IP and device, and CAPTCHA or other challenges before entering the waiting room. Queue tokens are bound to verified accounts, for example with phone OTP, and are single-use. I set per-account and per-payment-instrument ticket limits for each show, and enforce them in the hold step. Abuse signals include many accounts on one device, unusual speed, and repeated holds that never pay, and these trigger extra friction. Because holds are short and expire, bots cannot cheaply hoard seats. For the highest-demand events, named tickets or ID checks at entry reduce resale value. None of this is perfect, so I monitor and adjust during the sale.
17How would you design the QR ticket so venues can scan even with poor connectivity?Very often asked
The QR payload contains the booking ID, show ID, seats, an issue time and a digital signature. I would use asymmetric signing, so scanners hold only the public key and can verify authenticity offline, while the private key stays in a key management service. Before doors open, scanners download the ticket list for that show. They mark tickets as used locally and sync used events as soon as they can. With multiple offline devices, a duplicate could get through, so I prefer an online check whenever possible. I also keep offline windows short, and flag duplicates after sync. Key rotation uses a key ID inside the payload. The QR never contains personal data beyond what entry needs.
18Optimistic or pessimistic locking for the final booking step—what would you choose and why?Very often asked
I use optimistic, conditional updates: update where hold_id matches and status is HELD, or compare a version column. Row locks are held only for the instant of the update, so there is no long-lived SELECT FOR UPDATE. Pessimistic locks held across a payment would tie up connections for minutes and cause lock queues in a rush. Contention is already filtered by Redis holds, so conflicts at the DB are rare and cheap to detect, and zero affected rows simply means 'you lost'. Pessimistic locking fits cases with high conflict and short transactions. Here the long human step happens outside any transaction, which strongly favours the optimistic approach.
19A user's UPI payment shows pending as the hold is about to expire. How should the system behave?Very often asked
When the payment order is created and the user is redirected, I record that payment is in progress. The hold can then be extended once, up to a fixed limit, to cover common payment delays. It cannot be extended forever, or bad actors would hoard seats. The UI tells the user not to retry while the status is pending, which avoids double charges. A reconciliation job checks the gateway order status. If success arrives within the extended window, we confirm through the normal conditional update. If it arrives after, the user is refunded automatically and told clearly. Pending orders that end as failed release the hold right away.
20How do you handle a user selecting four seats when two of them are already taken?Often asked
The hold is all-or-nothing. The Lua script first checks every key in the group. If any seat exists, it returns which seats conflicted and sets nothing. If all are free, it sets them all with the same hold_id and TTL, and that whole step is atomic. This avoids partial holds, where a user ends up with two scattered seats and blocks them for others. The API returns the conflicting seat IDs and a fresh map, so the UI can suggest nearby alternatives. If the later DB hold insert fails, we delete the Redis keys, but only if they still carry our hold_id, so we never remove someone else's hold.
21Why use a Lua script instead of issuing separate SET NX commands from the application?Often asked
Separate commands are not atomic as a group. Two users could each win some seats of overlapping groups. Then both must roll back, and under contention neither gets seats. A Lua script runs atomically on the Redis node, so no other command runs between its check and its set. It also saves network round trips per seat. There are constraints. In Redis Cluster, every key the script touches must be in the same hash slot, so I use a hash tag like {show_id} in the key. Scripts must be short, because a long script blocks that node. The release script is also Lua, so it can compare the hold_id before it deletes.
22How does the idempotency key on seat selection work, and why is it needed?Often asked
The client creates a unique key for each selection attempt and sends it with the request. The booking service stores the key with the result, which is the hold_id or the error, scoped to the user and with a TTL. If a mobile client retries after a timeout, the same key returns the same hold instead of creating a second one. Without it, the user could hold two sets of seats, or have the retry fail because their own first hold made the seats look taken. Even if the server stores the request first, we must handle two copies arriving at once. Inserting the key under a unique constraint makes one request win and the other read its result.
23Two gates scan the same screenshot at the same moment. How do you ensure only one entry is allowed?Often asked
The scan service does an atomic conditional update: set status USED and record the scan time and gate, but only where the ticket ID matches and status is UNUSED. The database guarantees that only one of the two concurrent requests updates a row. That scanner shows green, and the other shows 'already used' with the time and gate of the first scan, which helps staff settle disputes. A Redis SET NX on the ticket ID works as a fast path, but the durable record matters for audits. Multi-seat bookings can track use per seat, so a group can enter in parts. Making the update conditional is what stops screenshot reuse.
24Walk me through a cancellation and refund while keeping state consistent.Often asked
First, check the show's refund policy, such as the cutoff time and refundable amount, against the booking. In one transaction, mark the booking CANCELLED, set the show_seat rows back to AVAILABLE with a new version, invalidate the QR, and write an outbox event. Then the payment service calls the gateway refund API, with an idempotency key derived from the booking ID, so retries never cause a double refund. Refund status is tracked separately (initiated, processed, failed) and reconciled with gateway reports. The seat map is updated from the event. If the refund call fails, the job retries. The seat release never waits for the money to arrive, but every refund is audited.
25How do you integrate theatres that also sell tickets at their own box office or through other platforms?Often asked
Selling the same seat on two channels is the risk, so there must be one authority for each show's seats. One option is quota allocation: the theatre assigns us a fixed block of seats, and we only sell those. That is simple, but seats can go unsold. The other option is real-time integration with the theatre's ticketing system, where our hold and confirm calls go to its API, which is authoritative, and we cache its seat state. That needs idempotent calls, timeouts, retries and a reconciliation report, plus a 'pending confirmation' state for when the partner is slow. Either way, the contract and reconciliation must be clear.
26What metrics and alerts would you put on this workflow?Often asked
For business health, I track hold success rate, hold-to-booking conversion, expired-hold rate, payment success by method, and refunds caused by late payments. For correctness, I track unique-constraint violations on booking, conditional updates that affected zero rows, Redis holds without DB rows, and any seat with more than one active booking. Any non-zero value there is a page. For the system, I track p99 latency of hold and confirm, Redis memory and failovers, DB replication lag, outbox backlog, webhook delay, and how long webhooks wait for reconciliation. For the waiting room, I track queue length, admission rate and estimated wait. I also add tracing across booking, payment and ticket using the hold_id.
27How do you prevent price tampering between seat selection and payment?Often asked
The client never sets the amount. When the hold is created, the booking service calculates the price on the server from the show's pricing, seat categories, fees and any valid offers. It stores that amount on the hold row. The payment order is created on the server with that amount and the hold_id. On the webhook, the decision step checks that the paid amount and currency match the hold and order exactly. If they don't match, the booking is not confirmed and a refund or review is triggered. Offer codes are checked and reserved on the server with usage limits. Webhook signatures stop forged success messages.
28What security and privacy obligations apply to user and payment data here?Often asked
For payments, I keep card data out of our systems by using the gateway's hosted checkout or tokenisation. That greatly reduces PCI DSS scope; we store only gateway references. For personal data like phone, email and booking history, India's Digital Personal Data Protection Act, 2023 applies. That means a clear purpose and consent, collecting only what is needed, reasonable security safeguards, breach handling, and honouring user rights such as correction and erasure, within legal retention needs. Technically, I encrypt data in transit and at rest, mask data in logs, use role-based access, and audit access to PII. QR codes carry no unnecessary personal data, and signing keys live in a KMS.
29How would you make the waiting room fair?Often asked
Users who arrive before the sale opens go into a pre-queue. At the start time, I randomise their order, so having the fastest refresh button or a bot does not help. People who arrive after opening are served first come, first served by their signed arrival time. Each position is tied to the account, so opening many tabs gives no advantage, because duplicates are merged or rejected. I show an honest position and estimated wait based on the current admission rate. If someone drops out, their admission token expires and the slot passes on. Admission speed adapts to downstream health and remaining inventory. When seats sell out, I tell the queue right away instead of leaving people waiting.
30How do you push live seat availability to users during a rush?Often asked
For hot shows, I push deltas over WebSockets or server-sent events. Each change, such as seat A5 held or released, is published to a channel for that show and sent to subscribed clients. Because the waiting room limits how many users are active, the number of connections stays manageable. For ordinary shows, polling the cached map with ETags or a version number is simpler and cheap. Updates may drop, so every message carries a version, and clients reload the full map when they see a gap. Live updates only reduce failed attempts. Correctness still comes from the atomic hold step.
31How would the design change for general admission events without assigned seats?Often asked
Without seat IDs, inventory is a count for each ticket category. A hold atomically reduces available quantity. In Redis, a Lua script checks that enough stock remains and then decrements it. In the DB, a conditional update such as 'set available = available minus n where available is at least n' prevents overselling. Each hold is still a row with expires_at, and the sweeper adds expired quantities back. A single hot counter can become a bottleneck. One fix is to split stock into several sub-counters, or pre-allocate batches to waiting room cohorts, with rebalancing later. Tickets get unique IDs and QR codes when the booking is confirmed, so venue scanning works the same way.
32How would you avoid leaving single isolated seats when users pick seats?Sometimes asked
Many cinemas don't want a single empty seat left stranded between bookings, because it rarely sells. The booking service can check a proposed selection against the current row state. It rejects or warns on choices that would leave a one-seat gap, and suggests a shifted block instead. This is a business rule checked on the server as part of hold validation. The client UI also applies it to give fast feedback. The rule uses a recent seat state, so a race can still leave a gap, and that is acceptable because it is an optimisation, not a correctness rule. I make it configurable per venue and relax it close to showtime.
33How would you test that the system never double books under a rush?Sometimes asked
First, I write concurrency tests where many workers try to hold and book the same seats. I assert that every seat has at most one BOOKED row and that every successful payment ends either booked or refunded. Then I run load tests that simulate opening-day traffic through the waiting room, to tune admission rate and find bottlenecks. Chaos tests add Redis failover, duplicate or out-of-order webhooks, lost webhooks, slow gateways and sweeper races. Property-based tests can generate random sequences of hold, pay, expire and cancel and check the invariants. In production, I run continuous invariant checks and reconciliation jobs, and alert on any violation.
Objective questions 33
1Which Redis command pattern best implements a temporary seat hold that frees itself?Asked almost every time
Why: SET with NX and EX is atomic: it succeeds only if the key does not exist and attaches an expiry, so abandoned holds release automatically.
2What does the conditional update 'set BOOKED where hold_id matches and status is HELD' achieve?Asked almost every time
Why: The update succeeds only if the row is still in the expected state. Stale or competing confirmations affect zero rows.
3What problem does the transactional outbox pattern solve here?Asked almost every time
Why: The event is written in the same transaction as the booking and published later by a relay. A crash can no longer separate the booking from its event.
4What stops a screenshot of a valid QR from being used twice?Asked almost every time
Why: A screenshot carries a valid signature, so the signature alone cannot stop reuse. Only the state change, marking the ticket used once, prevents a second entry.
5A captured payment's webhook was lost. What should recover it?Asked almost every time
Why: Pulling the status from the gateway covers lost webhooks. Reusing the idempotent handler avoids double processing.
6What is the final safeguard against double booking if the lock layer fails?Very often asked
Why: The database enforces the invariant transactionally, so a duplicate booking is rejected even when the cache lock was lost.
7In Redis, what does the NX option on SET do?Very often asked
Why: NX means 'only set if not exists', so the first caller wins the seat. Combined with EX or PX, the key also expires automatically.
8Why is a Lua script used to hold a group of seats in Redis?Very often asked
Why: Redis runs a script as a single atomic unit. That makes the check-then-set for all seats all-or-nothing.
9Seats return to AVAILABLE after a cancellation. Which design keeps a unique guard but still lets the seat be resold?Very often asked
Why: A plain unique index on history rows would block resale after a cancellation. A single row per seat, or a partial index on active bookings, keeps one active owner per seat.
10Why should the refund call include an idempotency key?Very often asked
Why: A retried request with the same key returns the original result and does not create a second refund.
11How is a payment webhook usually authenticated?Very often asked
Why: The signature proves the gateway sent the message and that it was not changed. Any order ID alone can be forged.
12Which query best describes what the sweeper does?Very often asked
Why: It releases only holds that are still HELD and have expired, using a conditional update. That avoids freeing seats that were just confirmed.
13Why can a Redis failover lead to a lost seat hold?Very often asked
Why: Writes that the primary acknowledged but had not yet replicated are lost when a replica is promoted. That is why the DB remains the final guard.
14Which shard key best fits the inventory database?Very often asked
Why: Holds, confirmations, releases and scans are all scoped to one show, so they stay single-shard and avoid distributed transactions.
15Assume 600,000 users are queued and the waiting room admits 1,000 users per second. Roughly how long until the last user is admitted?Very often asked
Why: 600,000 / 1,000 = 600 seconds, which is about 10 minutes.
16The same webhook arrives twice. What is the correct outcome?Very often asked
Why: Deduplicating on payment ID makes processing idempotent. Returning success also stops the gateway from retrying.
17Why should payment webhook handling be idempotent?Often asked
Why: Webhooks are delivered at least once, so deduplicating on payment id prevents double confirmation or double refunds.
18In Redis Cluster, how do you make sure a multi-key seat-hold script can run?Often asked
Why: Cluster requires all keys in one script to share a hash slot. A hash tag makes them hash on the same substring.
19What is the benefit of signing QR tickets with an asymmetric key pair?Often asked
Why: Verifying needs only the public key, while signing needs the private key kept in a KMS. Leaked scanners therefore cannot issue tickets.
20Which clock should be used to judge hold expiry in the decision step?Often asked
Why: Using one authoritative time source avoids clock skew between servers and devices, which could cause inconsistent decisions.
21Why is it acceptable for the seat map cache to be slightly stale?Often asked
Why: Correctness is enforced when the hold is taken and when the booking is confirmed. The map only affects user experience.
22What is the most effective way to reduce PCI DSS scope for card payments?Often asked
Why: If raw card data never touches our systems, far fewer of them are in PCI scope. We keep only tokens or references.
23A mobile client retries a seat-selection request with the same idempotency key after a timeout. What should happen?Often asked
Why: Idempotency means a repeated request gives the same result without new side effects.
24How does optimistic locking with a version column detect a conflicting update?Often asked
Why: If another writer has bumped the version, the conditional update matches no rows, and the conflict is detected.
25For a general admission event, how do you safely reserve n tickets from a counter in SQL?Often asked
Why: The conditional decrement is atomic and fails when stock is not enough. Read-modify-write in the app races and oversells.
26Which waiting room behaviour is fairest for users who arrive before the sale starts?Often asked
Why: Randomising the early arrivals removes the advantage of refresh speed and bots. Later arrivals keep fair arrival order.
27Which control most directly limits scalpers hoarding seats?Often asked
Why: Limits enforced on the server cap how much one person can take. Short holds stop cheap hoarding.
28Why should the countdown shown to the user end slightly before the server-side hold expiry?Often asked
Why: A small buffer avoids disputes where a payment started within the visible window lands just after server expiry.
29When releasing a Redis hold, why should the script compare the stored hold_id before deleting?Often asked
Why: Once a hold expires, another user may own the key. A compare-and-delete removes only your own hold.
30Where should the payable amount for a hold come from?Often asked
Why: Prices set on the server stop tampering. Matching the paid amount to the hold before confirming catches mismatches.
31For live seat-map updates on a hot show, which transport is most suitable?Sometimes asked
Why: Push channels send small updates as they happen. That cuts stale picks without heavy polling.
32Which Indian law mainly governs how the platform processes users' digital personal data?Sometimes asked
Why: The DPDP Act, 2023 sets India's rules for consent, purpose limits, safeguards and data principal rights for digital personal data.
33What is the main downside of giving a partner theatre a fixed seat quota instead of real-time integration?Sometimes asked
Why: Fixed quotas avoid conflicts but split the inventory, so demand and supply can end up stuck in different channels.
Track your progress through every blueprint in your dashboard.
Start learning