Skip to content
asyncsouravPublic

About

Production-grade event ticketing platform — concurrency-safe seat booking (optimistic locking), Redis-cached listings, anti-scalping rate limiting, and live seat availability over WebSockets. Built with Spring Boot + React.

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

79 Commits

Folders and files

Repository files navigation

QuickTix

A production-grade, distributed event ticketing and seat reservation platform built with Java 25, Spring Boot 4, PostgreSQL 16, Docker, and React.

QuickTix addresses high-concurrency seat booking scenarios where multiple users attempt to reserve the same seat simultaneously. The platform guarantees strict consistency and zero double-bookings through database-level transactions and optimistic locking.

Live Deployment: https://quicktix-weld.vercel.app/


Architecture Overview

QuickTix operates as a decoupled client-server architecture:

[ Client: React + Vite ] 
       | (HTTPS / REST)
       v
[ Reverse Proxy / Cloud Gateway ]
       | (Port 8080)
       v
[ Spring Boot 4 Backend Application ]
   ├── Spring Security (Stateless JWT Filter)
   ├── Controller Layer (22 REST Endpoints, OpenAPI 3.0)
   ├── Service Layer (Business Rules & Ownership Enforcement)
   └── Persistence Layer (Spring Data JPA / Hibernate ORM)
       └── Database Concurrency (@Version Optimistic Locking)
               |
               v (JDBC Pool - HikariCP)
[ PostgreSQL 16 Database ] (Containerized / Persistent Volume)

Core Engineering Highlight: Concurrency Control

Ticket booking platforms encounter severe concurrency bottlenecks during high-demand on-sale windows. Without robust concurrency controls, simultaneous requests result in race conditions, phantom reads, and double-sold seats.

Concurrency Mechanism

QuickTix implements Optimistic Concurrency Control (OCC) combined with declarative database transactions:

  1. Entity Versioning: The Seat entity incorporates a @Version private Long version; field managed by Hibernate.
  2. Atomic Batch Processing: Seat reservations execute within a @Transactional boundary across a collection of seat IDs (List<Long> seatIds).
  3. Collision Detection: When concurrent requests attempt to reserve the same seat, the first committing transaction succeeds and increments the version column (UPDATE seats SET status = 'BOOKED', version = version + 1 WHERE id = ? AND version = ?).
  4. Automated Rollback: Conflicting concurrent transactions fail the version predicate, triggering an ObjectOptimisticLockingFailureException. The Spring transaction manager immediately rolls back all seat modifications in the batch.
  5. Deterministic Error Handling: A centralized GlobalExceptionHandler intercepts the collision and produces a standardized 409 Conflict response with human-readable diagnostic details.

Empirical Verification (Race Condition Test)

A high-concurrency simulation dispatching 10 parallel requests (Promise.all) for the exact same seat within 1 millisecond yields deterministic isolation:

Request Index HTTP Status Response Payload Result
Request 1 201 Created {"success": true, "message": "Booking confirmed successfully"} Seat Reserved
Request 2 409 Conflict {"status": 409, "message": "This seat was just selected or booked..."} Rejected
Request 3 409 Conflict {"status": 409, "message": "This seat was just selected or booked..."} Rejected
Request 4 409 Conflict {"status": 409, "message": "This seat was just selected or booked..."} Rejected
Request 5 409 Conflict {"status": 409, "message": "This seat was just selected or booked..."} Rejected
Request 6 409 Conflict {"status": 409, "message": "This seat was just selected or booked..."} Rejected
Request 7 409 Conflict {"status": 409, "message": "This seat was just selected or booked..."} Rejected
Request 8 409 Conflict {"status": 409, "message": "This seat was just selected or booked..."} Rejected
Request 9 409 Conflict {"status": 409, "message": "This seat was just selected or booked..."} Rejected
Request 10 409 Conflict {"status": 409, "message": "This seat was just selected or booked..."} Rejected

Technology Stack

Backend Infrastructure

Frontend Client

  • Framework & Tooling: React 19, Vite 6
  • Routing: React Router 6 (Role-protected route guards)
  • HTTP Client: Axios (Configured request/response interceptors for Bearer auth)
  • Styling & Design System: Custom Vanilla CSS Design System with theme tokens (Light / Dark mode toggle)
  • Hosting: Vercel (Edge CDN deployment with SPA client rewrite rules)

Repository Architecture

quicktix/
├── client/                     # Frontend Single Page Application (React + Vite)
│   ├── src/                    # Components, pages, context providers, API client
│   ├── vercel.json             # Vercel SPA routing rewrites
│   └── package.json            # Node.js dependencies
├── server/                     # Backend REST API Service (Spring Boot 4)
│   ├── src/main/java/          # Controllers, services, JPA repositories, entities, security
│   ├── src/main/resources/     # Profiles (application.yml, application-dev, application-prod)
│   ├── Dockerfile              # Multi-stage optimized production build
│   └── pom.xml                 # Maven build configuration (Java 25)
├── docker-compose.yml          # Full-stack container orchestration
├── .env.example                # Environment variable specification template
└── README.md                   # Project documentation

Quick Start (Containerized Stack)

The entire backend and database stack can be spun up with a single command using Docker Compose.

Prerequisites

1. Clone Repository & Setup Environment

git clone https://github.com/asyncsourav/quicktix.git
cd quicktix

# Copy environment variables
cp .env.example .env

2. Start Full Backend Stack (PostgreSQL + Spring Boot)

docker compose up -d --build

Docker Compose will:

  1. Boot PostgreSQL 16 with a persistent named volume (postgres_data).
  2. Run healthchecks via pg_isready until the database is ready to accept connections.
  3. Build the backend using a multi-stage Docker build with Java 25.
  4. Launch the Spring Boot application on port 8080.
  5. Seed demo accounts, venues, events, and seat maps automatically on first run.

Verify that both containers are running and healthy:

docker compose ps

3. Launch Frontend Client

cd client
npm install
npm run dev

The client application will start at http://localhost:5173 (or http://localhost:3000).


Interactive API Documentation

QuickTix features full interactive OpenAPI 3.0 documentation via Swagger UI.

API Endpoint Registry (22 Endpoints)

Domain Method Endpoint Authorization Description
Auth POST /api/auth/register Public Register new account with BCrypt password hashing
POST /api/auth/login Public Authenticate credentials and receive signed JWT
Events GET /api/events Public Query events with category and keyword search filters
GET /api/events/{id} Public Retrieve detailed event metadata
GET /api/events/{id}/seats Public Fetch current seat layout and availability status
POST /api/events Organizer / Admin Publish event and auto-generate seat layout
PUT /api/events/{id} Organizer / Admin Update event details (organizer ownership enforced)
DELETE /api/events/{id} Organizer / Admin Delete event (organizer ownership enforced)
Venues GET /api/venues Public List all registered venues
GET /api/venues/{id} Public Retrieve venue specifications and capacity
GET /api/venues/organizer/{id} Public List venues managed by an organizer
POST /api/venues Organizer / Admin Register new venue
PUT /api/venues/{id} Organizer / Admin Update venue details (ownership enforced)
DELETE /api/venues/{id} Organizer / Admin Remove venue (ownership enforced)
Bookings POST /api/bookings Authenticated Atomic multi-seat reservation with optimistic locking
GET /api/bookings/me Authenticated Retrieve authenticated user booking history
GET /api/bookings/{id} Authenticated Retrieve booking receipt (ownership verified)
DELETE /api/bookings/{id} Authenticated Cancel booking and release seats back to inventory
Admin GET /api/admin/users Admin Administrative user directory audit
GET /api/admin/stats Admin Real-time aggregate revenue and utilization metrics
GET /api/admin/bookings Admin Platform-wide transaction ledger audit
Health GET /api/ping Public Service liveness probe

Production Docker Optimization

The backend employs an optimized multi-stage Dockerfile:

# Stage 1: Build stage with compiler and dependencies
FROM maven:3.9-eclipse-temurin-25-alpine AS build
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests

# Stage 2: Runtime stage with minimal Alpine JRE
FROM eclipse-temurin:25-jre-alpine
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Container Metric Comparison

  • Single-Stage Build (Legacy baseline): 870 MB
  • Multi-Stage Build (Production): 434 MB
  • Image Size Reduction: 50.11% (436 MB eliminated from production container)
  • Content Layer Size Reduction: 55.81% (from 310 MB to 137 MB)

Seed Data & Demo Credentials

When launched against an uninitialized database, DataInitializer seeds test accounts with password password123:

Role Email Password Permissions
Admin admin@quicktix.com password123 System oversight, aggregate metrics, platform audit
Organizer organizer@quicktix.com password123 Venue management, event creation, seat generation
Attendee (User) user@quicktix.com password123 Event browsing, seat reservation, booking management

Engineering Roadmap

  • Phase 1: Core Domain Model, JPA Repositories, REST API Endpoints
  • Phase 2: Role-Based Access Control (RBAC), Stateless JWT Security, Password Hashing
  • Phase 3: Optimistic Locking Concurrency Control (@Version), Race Condition Verification
  • Phase 4: OpenAPI 3.0 / Swagger UI Interactive Documentation (springdoc-openapi)
  • Phase 5: Multi-Stage Docker Containerization, Full-Stack Docker Compose Orchestration
  • Phase 6: Dual rotating JWT refresh tokens with token family reuse detection
  • Phase 7: Distributed caching with Redis for hot read paths (event listings, seat maps)
  • Phase 8: Distributed API rate limiting via Bucket4j and token bucket algorithms
  • Phase 9: Real-time seat reservation broadcasts over WebSocket / STOMP protocol
  • Phase 10: Automated test coverage (JUnit 5, Mockito, Testcontainers for PostgreSQL)
  • Phase 11: Continuous Integration pipeline via GitHub Actions
  • Phase 12: High-load performance testing via k6

Author

Sourav Kumar

About

Production-grade event ticketing platform — concurrency-safe seat booking (optimistic locking), Redis-cached listings, anti-scalping rate limiting, and live seat availability over WebSockets. Built with Spring Boot + React.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages