FairHold is a backend-only reservation system built with Spring Boot. It allows users to view resources, create time slots, temporarily hold a slot, confirm a booking before the hold expires, and prevent double booking.
The project is designed as an interview-friendly backend MVP focused on reservation workflows, Redis-based temporary holds, clean layered architecture, and practical backend development concepts.
- User signup
- User login
- Password hashing using BCrypt
- JWT token generation on successful login
- Global exception handling
- Validation error handling
- Resource creation and listing
- Slot creation and listing
- Available slots API
- Temporary slot hold using Redis TTL
- First-come-first-serve hold behavior using Redis
setIfAbsent - Booking confirmation from temporary holds
- Booking cancellation
- User booking history
- All bookings API
- Swagger/OpenAPI documentation
- Docker-based Redis setup
- Java 21
- Spring Boot 4
- Spring Web MVC
- Spring Data JPA
- Spring Security
- PostgreSQL
- Redis
- Docker
- Maven
- Lombok
- Bean Validation
- Swagger/OpenAPI
FairHold follows a simple layered architecture:
Controller
↓
Service
↓
Repository
↓
Database / Redis
The controller layer receives HTTP requests, validates request bodies, calls service methods, and returns HTTP responses.
The service layer contains the main business logic, such as user registration, login, slot creation, temporary holds, booking confirmation, and booking cancellation.
The repository layer communicates with PostgreSQL using Spring Data JPA.
Redis is used for temporary hold storage with automatic expiry.
Create Resource
↓
Create Slot
↓
User places temporary hold on slot
↓
Redis stores hold with TTL
↓
User confirms booking before hold expires
↓
Booking is saved in PostgreSQL
↓
Slot becomes unavailable
POST /api/auth/signup
POST /api/auth/loginPOST /api/resources
GET /api/resourcesPOST /api/slots
GET /api/slots
GET /api/slots/available
GET /api/slots/resource/{resourceId}POST /api/holdsPOST /api/bookings/confirm
GET /api/bookings
GET /api/bookings/user/{userId}
PATCH /api/bookings/{bookingId}/cancelCreate a PostgreSQL database named:
fairhold
Update database credentials in:
src/main/resources/application.yml
Example:
spring:
datasource:
url: jdbc:postgresql://localhost:5432/fairhold
username: postgres
password: your_password
jpa:
hibernate:
ddl-auto: update
show-sql: trueCreate and start Redis container:
docker run --name fairhold-redis -p 6379:6379 -d redisIf the container already exists:
docker start fairhold-redisCheck Redis:
docker exec -it fairhold-redis redis-cli pingExpected output:
PONG
For Linux/macOS:
./mvnw spring-boot:runFor Windows:
.\mvnw.cmd spring-boot:runThe application runs at:
http://localhost:8080
Swagger UI is available at:
http://localhost:8080/swagger-ui/index.html
Swagger can be used to view and test all APIs.
com.fairhold
│
├── config
├── controller
├── dto
│ ├── request
│ └── response
├── entity
├── repository
├── security
├── service
│ └── impl
├── exception
├── util
└── FairholdApplication