A full-stack microservices-based car rental platform built with Spring Boot, React, RabbitMQ, Redis, and MongoDB. Users can search rental agencies by city, browse vehicles, make bookings with real-time availability checks, confirm payments, and cancel bookings with automatic refund processing.
βββββββββββββββββββ
β React Frontend β
β (Vite + React) β
ββββββββββ¬βββββββββ
β HTTP
ββββββββββΌβββββββββ
β API Gateway β β JWT validation
β (Port 8090) β β Route forwarding
ββββββββββ¬βββββββββ
β
ββββββββββββββββββββΌβββββββββββββββββββ
β β β
ββββββββββββΌβββββββ ββββββββββΌββββββββ ββββββββββΌβββββββββ
β UserService β β AgencyService β β BookingService β
β (Port 8081) β β (Port 8082) β β (Port 8083) β
βββββββββββββββββββ ββββββββββββββββββ ββββββββββ¬βββββββββ
β
ββββββββββΌβββββββββ
β PaymentService β
β (Port 8085) β
βββββββββββββββββββ
All services register with Eureka (Port 8761) for service discovery.
BookingService β PaymentService communicate via RabbitMQ.
AgencyService + BookingService use Redis for caching and distributed locking.
1. User searches agencies by source city
2. Selects agency β browses vehicles
3. Clicks "Book Now"
β BookingService creates booking (status: PENDING)
β Redis locks vehicle dates (prevents double booking)
4. User clicks "Confirm" in modal
β BookingService publishes BookingCreatedEvent to RabbitMQ
β PaymentService consumes event β processes mock payment
β On SUCCESS: publishes PaymentSuccessEvent β BookingService sets status: CONFIRMED
β On FAILURE: publishes PaymentFailedEvent β BookingService sets status: CANCELLED, releases Redis locks
5. Scheduled job runs daily at midnight
β Marks CONFIRMED bookings past end date as COMPLETED
1. User cancels a CONFIRMED booking
β BookingService publishes BookingCancelledEvent to RabbitMQ
β PaymentService consumes event β processes mock refund
β On SUCCESS: publishes RefundSuccessEvent β BookingService sets status: REFUNDED
β On FAILURE: logs error
2. Frontend polls every 2 seconds for up to 30 seconds
β Updates UI when status changes to REFUNDED/CANCELLED
Load tested with k6 under 50 concurrent virtual users for 30 seconds.
| Metric | Result |
|---|---|
| Total Requests | 1,567 |
| Throughput | ~50 requests/sec |
| Avg Response Time | 481ms |
| Min Response Time | 16ms (Redis cache hit) |
| p(90) Response Time | 848ms |
| Failure Rate | 0% |
Endpoints tested:
POST /api/agency/searchβ paginated agency search with Redis cachingGET /api/user/profileβ authenticated user profile retrieval
Tested on local Docker Compose stack (6 services + MongoDB + Redis + RabbitMQ) running on a development machine. Production performance would be significantly higher.
| Layer | Technology |
|---|---|
| Frontend | React 18, Vite, React Router |
| Backend | Spring Boot 3, Spring Cloud Gateway |
| Service Discovery | Netflix Eureka |
| Messaging | RabbitMQ (with Dead Letter Queues) |
| Cache / Locking | Redis |
| Database | MongoDB |
| Auth | JWT with Refresh Token Rotation (HMAC-SHA512) |
| Build | Maven |
| Infrastructure | Docker, Docker Compose |
Car-Rental-System/
βββ Backend/
β βββ eureka/ # Service registry (Port 8761)
β βββ Gateway/ # API Gateway + JWT filter (Port 8090)
β βββ UserService/ # Auth + user profile (Port 8081)
β βββ AgencyService/ # Agencies + vehicles + search (Port 8082)
β βββ BookingService/ # Booking lifecycle + scheduling (Port 8083)
β βββ PaymentService/ # Mock payment + refund processing (Port 8085)
β βββ docker-compose.yaml # Full stack orchestration
βββ Frontend/
βββ src/
β βββ Pages/ # Login, Register, Home, AgencyPage, VehicleDetails, MyBookings, Profile
β βββ Components/ # Header, Sidebar, Footer, ProtectedRoute
β βββ Hooks/ # Custom React hooks
β βββ Services/ # Axios API calls with auto token refresh
βββ package.json
- Docker + Docker Compose
- Node.js 18+ (for frontend only)
git clone https://github.com/your-username/Car-Rental-System.git
cd Car-Rental-SystemCreate a .env file inside the Backend/ folder:
JWT_SECRET_KEY2=your-secret-key-minimum-32-characters-long
cd Backend
docker-compose up --buildThis single command builds and starts everything:
- MongoDB, Redis, RabbitMQ (infrastructure)
- Eureka (service registry)
- Gateway, UserService, AgencyService, BookingService, PaymentService
Wait until you see Started ... in X seconds in the logs for all services. Verify everything is up at http://localhost:8761 β all 5 services should show as UP.
cd Frontend
npm install
npm run devApp runs at http://localhost:5173
# Run in background
docker-compose up --build -d
# Stop everything
docker-compose down
# View logs for a specific service
docker-compose logs -f booking-service
# Rebuild a single service after code change
docker-compose up --build booking-serviceSwitch application.yml in every service to active: prod and set the following environment variables on your deployment platform:
| Variable | Used By | Description |
|---|---|---|
MONGODB_URI |
All services | MongoDB Atlas connection URI |
REDIS_HOST |
AgencyService, BookingService | Redis Cloud host |
REDIS_PORT |
AgencyService, BookingService | Redis Cloud port |
REDIS_PASSWORD |
AgencyService, BookingService | Redis Cloud password |
RABBITMQ_HOST |
BookingService, PaymentService | RabbitMQ host |
RABBITMQ_USERNAME |
BookingService, PaymentService | RabbitMQ username |
RABBITMQ_PASSWORD |
BookingService, PaymentService | RabbitMQ password |
JWT_SECRET_KEY |
Gateway, UserService | HMAC secret (min 32 chars) |
FRONTEND_URL |
Gateway | Frontend origin for CORS |
All requests go through the Gateway at http://localhost:8090.
All endpoints except /api/auth/** require Authorization: Bearer <token> header.
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/auth/signup |
Register new user |
| POST | /api/auth/login |
Login, returns access token + refresh token |
| POST | /api/auth/refresh |
Exchange refresh token for new access token |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/user/profile |
Get logged-in user's profile |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/agency/search |
Search agencies by source city (paginated) |
| GET | /api/agency/{agencyId} |
Get agency details with vehicles |
| GET | /api/agency/vehicle/{vehicleId} |
Get vehicle details |
| POST | /api/agency/register |
Register a new agency |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/booking |
Create a booking (status: PENDING) |
| PUT | /api/booking/confirm/{bookingId} |
Confirm booking β triggers payment |
| PUT | /api/booking/cancel |
Cancel a confirmed booking β triggers refund |
| GET | /api/booking/my |
Get all bookings for logged-in user |
| Queue | Routing Key | Publisher | Consumer |
|---|---|---|---|
booking.created.queue |
booking.created.key |
BookingService | PaymentService |
booking.cancelled.queue |
booking.cancelled.key |
BookingService | PaymentService |
| Queue | Routing Key | Publisher | Consumer |
|---|---|---|---|
payment.success.queue |
payment.success |
PaymentService | BookingService |
payment.failed.queue |
payment.failed |
PaymentService | BookingService |
payment.refund.queue |
payment.refund |
PaymentService | BookingService |
payment.dead.letter.queue |
payment.dead |
DLX | β |
- JWT tokens are validated at the Gateway before forwarding to any service
- 30-minute access tokens + 7-day refresh tokens with rotation stored in MongoDB
- Frontend axios interceptor automatically refreshes expired tokens and retries the original request
- Gateway injects
X-User-IdandX-Usernameheaders for downstream services - All booking operations verify the requesting user owns the booking
- Passwords are BCrypt encoded
/api/auth/**is the only public route β all others require a valid JWT
# BookingService
cd Backend/BookingService && mvn test
# UserService
cd Backend/UserService && mvn test
# AgencyService
cd Backend/AgencyService && mvn test
# PaymentService
cd Backend/PaymentService && mvn testTests cover service layer (unit tests with Mockito) and controller layer (MockMvc) across all 4 services β 35+ test cases covering Redis locking rollback, RabbitMQ event publishing, JWT refresh token rotation, and booking lifecycle across 6 status transitions.
| Service | Port |
|---|---|
| Eureka Dashboard | 8761 |
| API Gateway | 8090 |
| UserService | 8081 |
| AgencyService | 8082 |
| BookingService | 8083 |
| PaymentService | 8085 |
| MongoDB | 27017 |
| Redis | 6379 |
| RabbitMQ AMQP | 5672 |
| RabbitMQ Management UI | 15672 |
| Frontend | 5173 |
- Payment is mocked via
MockPaymentProviderβ real payment gateway integration (Razorpay/Stripe) planned - Cost calculation currently uses
pricePerKm Γ daysβ Google Maps Distance Matrix API integration planned for actual route distance - Search currently filters by source city only β destination city filter planned
- No admin panel for agency management
Built as a portfolio project demonstrating microservices architecture, event-driven design, and full-stack development.
Hope you found something useful in here! Drop a star if you did β it keeps this project (and me) motivated πΎ
