Skip to main content
Scale Evolution Timeline
6 rungs · 10K → 1B RPS

Ticket Booking: Junior → Architect Evolution

The mandated interactive flow. Step through each rung, ask what breaks FIRST, weigh the options, and defend the chosen architecture. This is how architectural thinking is learned — not by reading a fixed design, but by tracing how it evolves under growth pressure.

Back to Ticket Booking

Scale Evolution Timeline

Step through 6 architectural rungs, from 10K RPS to 1B RPS. At each rung, ask: what will break FIRST? Why? What options exist? Which one do we pick — and what are we accepting?

This is the reasoning cycle that separates a Junior developer ("here's an architecture") from an Architect ("here's why this architecture, why now, and what breaks next").

Rung 1 of 610K RPS
10K RPS

10K RPS — Postgres SELECT FOR UPDATE + seat map

1. Current architecture

Where we are before growth pressure

3 Rails apps + Postgres db.r6i.large. Tables: `events, seats(seat_id, event_id, section, row, number, status)`, `bookings`. Seat selection: `SELECT * FROM seats WHERE event_id=? AND status='available' FOR UPDATE SKIP LOCKED`. Booking: `UPDATE seats SET status='held', held_by=?, held_until=NOW()+INTERVAL '10 minutes' WHERE seat_id=?`.

2. Growth trigger

What changed — the traffic/data force

MVP. Small events (500-5000 seat venues). 100K registered users, ~200 events/month. Peak 10K RPS mostly browse, occasional 500 concurrent buyers per event.

3. Bottleneck — what breaks FIRST?

The component that saturates as growth arrives

Bottleneck component

None yet — SELECT FOR UPDATE works

Why it breaks

500 concurrent buyers × 30-second selection window = 15 concurrent locks. Postgres row-level locking handles this. p99 seat selection: 200-500ms. No overselling because SELECT FOR UPDATE serializes access.

Signal you'd see

Postgres CPU 30%, concurrent locks per event p99 50, seat selection latency 400ms p99, oversell incidents 0

4. Options — what could we do?

Alternatives an architect must consider before picking

Do nothing — Postgres FOR UPDATE is right at MVP
CHOSEN
  • + Full ACID guarantees — no oversell risk
  • + Simple architecture, familiar SQL
  • + Team ships fast
  • Ceiling around 5K concurrent buyers per event (lock contention)
  • Row-level locking serializes hot rows (concert front-row = single-row hotspot)
  • No queue for popular events — first-come-first-served UX chaos
$400/mo

5. Chosen

The specific decision we're making

Do nothing — Postgres FOR UPDATE is right at 10K RPS with small venues

6. Trade-offs

What we're explicitly accepting to move forward

  • Accept ceiling around 5K concurrent buyers per event
  • Accept row-level lock contention on hot seats
  • Accept first-come-first-served UX (no queue)
  • Accept ceiling around 30-50K RPS baseline

7. New architecture

The system after this decision — headroom for the next 5-10x

3 Rails apps + Postgres. SELECT FOR UPDATE SKIP LOCKED for seat selection. Total cost: $400/mo.

Estimated: $400/mo

8. Next bottleneck — what will break at the NEXT rung?

This is the seed of the next rung

At ~100K RPS when major artist announces tour (100K fans hit at 10am on-sale), Postgres serializes on hot seats → 30-90s waits + timeouts. Users refresh + retry → double the load. Need distributed locking + queue-based selection. L5 shape.

What comes next in your Junior → Architect journey

You've traced 6 rungs of Ticket Booking evolution. Now try the same reasoning cycle on a system you don't know yet — pick from the Systems catalog and answer the same questions: current arch → growth trigger → bottleneck → options → chosen → trade-offs → new arch → next bottleneck. That is architecture.