← Selected work

Case study

CinePlex — Movie Ticket Booking System

Overview

A full-stack movie-ticket booking platform built with Java 21, Spring Boot, PostgreSQL and React. It covers movie and showtime discovery, seat selection, and a booking and payment flow designed to stay correct under concurrent demand for the same seats. A conversational AI assistant, built with Spring AI and Gemini tool-calling, can search shows and place bookings on the user's behalf.

Problem / Context

Seat booking is a classic concurrency problem: two users can select the same seat at the same moment, and naive checks let both bookings through. The system needs a reservation model that holds seats safely during checkout, releases them on timeout or cancellation, and never double-sells.

My Contribution

Built the whole system — backend, database design, frontend and the AI assistant.

  • Spring Boot REST services for movies, showtimes, seat inventory, bookings and payments
  • Concurrency-safe seat booking using database-level pessimistic locking
  • Transactional hold / confirm / cancel flow with automatic release of expired holds
  • Dynamic pricing — weekday, weekend and premium rates — via a Strategy-pattern pricing layer
  • React frontend for discovery, seat-map selection and checkout
  • Agentic AI booking assistant with Spring AI + Gemini tool-calling, containerised with Docker

Technical Architecture

React client → Spring Boot REST API
Booking request → @Transactional service
→ SELECT ... FOR UPDATE on the target seat rows (pessimistic lock)
→ create HOLD with expiry → return hold reference
Confirm → payment → HOLD → CONFIRMED (same transaction)
Scheduler → releases expired HOLDs back to available
Pricing → Strategy pattern (weekday / weekend / premium)
AI assistant → Spring AI + Gemini tool-calling → same booking API
PostgreSQL · Docker

Key Engineering Challenges

Preventing double-booked seats

Concurrent requests for the same seat must not both succeed, and the check has to survive race windows between "is it free?" and "book it".

Solution: pessimistic row locks (SELECT ... FOR UPDATE) on the seat rows inside a single transaction, so a competing transaction blocks until the first commits or rolls back, then re-reads the true state.

Holds that never leak inventory

A seat held during checkout must be released if the user abandons or payment fails — without a manual cleanup step.

Solution: an explicit hold / confirm / cancel state model with expiry timestamps and a scheduled job that returns lapsed holds to the available pool.

Letting an AI agent book safely

The assistant needed to take real actions (search, hold, confirm) rather than just answer questions.

Solution: expose booking operations as Spring AI tools that call the same transactional service the UI uses, so the concurrency and pricing guarantees hold regardless of caller.

Impact

  • Demonstrates backend depth — Java / Spring Boot, PostgreSQL, transactions and concurrency control
  • Concurrency-safe booking with no double-sold seats under parallel load in testing
  • End-to-end AI integration: an agent that transacts through the real booking API

Tech Stack

Java 21 · Spring Boot · Spring AI · PostgreSQL · React · Docker · Gemini (tool-calling)