RizTech Academy logo
RizTech Academy
Mobile AppOpen source

Showtime — Cinema Seat Booking

Cinema ticket booking with five-minute seat holds: a Ktor API on PostgreSQL and a Flutter app. When two people tap the same seat at the same instant, exactly one of them gets it.

Mobile App Development, Flutter, Backend & APIs, Testing & CI
Showtime — Cinema Seat Booking — Mobile App case study
Screens

See it running

Android

Android emulator against the live API. iOS has not been run yet.

  • Showtime film list for Pune Cinemas showing five films with language, running time and certificate
    Films
  • Seat map for Dune: Part Two with three seats in row D selected, a ₹630 total and a Hold seats button
    Pick seats
  • Confirm booking screen with a countdown showing the seats are held for 4 minutes 55 seconds and a Pay button
    Seats held while you pay
  • Seat map showing seats held by someone else outlined in amber and booked seats greyed out
    Held by someone else, and booked
  • Booked ticket card for Dune: Part Two with seats G5 and G6, the amount paid and a booking reference
    Ticket

The problem

Listing films and tapping seats is the easy half. A ticketing system lives or dies on the hold: picking a seat reserves it for five minutes while you pay. Two people tapping the same seat must not both get it, an expired hold must free its seat even if a background job has died, and confirming a hold that lapsed a millisecond ago must fail before any money moves.

How it’s built

A unique index over unreleased holds makes the database settle every race: the second insert simply collides. Taking a hold first releases lapsed holds in the same transaction, and availability compares the expiry with the database clock, so a seat comes back the instant its hold runs out, with no sweeper. Confirmation checks expiry inside the insert itself, and a unique constraint on booked seats is the final guard. In the app, the countdown runs against the server’s deadline rather than the phone’s clock, and “someone else has those seats”, “your hold ran out” and “the server did not answer” are three different messages.

What it does

  • Twenty threads racing for one seat: exactly one hold
  • Expired holds free their seats instantly, with no background job
  • A lapsed hold cannot be confirmed, so no one pays for a seat they do not have
  • Available, selected, held by someone and booked: four seat states shown at once
  • Booked end to end on an Android emulator against the live API

Learn to build software like this

The free courses teach the same craft — from the basics to a real, running project.