A production-grade microservices SaaS platform for shared mobility services (scooters, bikes, cars), decomposed from a monolithic architecture into independent, scalable services.
The platform consists of 8 microservices built with Java 17, Spring Boot 3.x, and Spring Cloud:
External Clients
│
▼
┌─────────────────────┐
│ API Gateway :9000 │ (Spring Cloud Gateway + Auth + Rate Limiting)
└──────────┬──────────┘
│ lb://service-name
┌──────┼──────┬────────┬────────┐
▼ ▼ ▼ ▼ ▼
User Vehicle Location Ride Payment
:8081 :8082 :8083 :8084 :8085
Eureka :8761 │ │ │ │
Service │ │ │ │ │
Registry│ │ │ │ │
│ │ │ └─────┤
│ │ │ │
│ └───Kafka───┘
│ :9093 gRPC
│
└──────────────┐
│
Redis (GeoHash) │
Kafka (Events) │
MySQL (per svc) │
| Service | Port | Description |
|---|---|---|
| Service Registry | 8761 | Netflix Eureka server |
| API Gateway | 9000 | Routing, auth, rate limiting |
| User Service | 8081 | Registration, JWT auth, profiles |
| Vehicle Service | 8082 | CRUD, status, gRPC server (:9092) |
| Location Service | 8083 | GeoHash index, Kafka consumer, gRPC (:9093) |
| Ride Service | 8084 | Ride lifecycle management |
| Payment Service | 8085 | Payment processing, idempotency |
- Precision-7 GeoHash grids (~153m x 153m cells)
- Overlapping grid regions: each vehicle stored in 4 adjacent grids to eliminate boundary-miss errors
- < 30ms P99 nearest-vehicle query latency
- Redis-backed for high-performance geo queries
- IoT devices publish to Kafka topic
vehicle-location-updates - Location Service batch-consumes (100 messages/poll, 6 concurrent threads)
- Atomic Redis GeoHash index updates
- Dead Letter Queue (DLQ) for failed messages
- Supports 50,000 vehicles @ 30s update interval (~1,667 msg/s)
- gRPC for synchronous, contract-enforced IPC (Vehicle Service <-> Location Service)
- OpenFeign for REST-based service calls
- Kafka for async event streaming (ride events, payment events)
- Java 17, Spring Boot 3.2.5, Spring Cloud 2023.0.1
- Eureka (Service Registry) + Spring Cloud Gateway (API Gateway)
- Redis (GeoHash, caching, session) + Kafka (Event streaming)
- MySQL (per-service databases)
- gRPC (internal contracts) + Protocol Buffers 3
- JWT (authentication) + BCrypt (password hashing)
- Java 17+
- Maven 3.9+
- Docker & Docker Compose
docker compose up -dThis starts: Zookeeper, Kafka, Redis, and 4 MySQL instances (user_db, vehicle_db, ride_db, payment_db).
mvn clean install -DskipTests# Terminal 1: Service Registry
cd service-registry && mvn spring-boot:run
# Terminal 2: API Gateway
cd api-gateway && mvn spring-boot:run
# Terminal 3: User Service
cd user-service && mvn spring-boot:run
# Terminal 4: Vehicle Service
cd vehicle-service && mvn spring-boot:run
# Terminal 5: Location Service
cd location-service && mvn spring-boot:run
# Terminal 6: Ride Service
cd ride-service && mvn spring-boot:run
# Terminal 7: Payment Service
cd payment-service && mvn spring-boot:run- Eureka Dashboard: http://localhost:8761
- API Gateway: http://localhost:9000
# Register
curl -X POST http://localhost:9000/api/users/register \
-H "Content-Type: application/json" \
-d '{"username":"alice","email":"alice@example.com","password":"secret123"}'
# Login
curl -X POST http://localhost:9000/api/users/login \
-H "Content-Type: application/json" \
-d '{"username":"alice","password":"secret123"}'# Register a vehicle
curl -X POST http://localhost:9000/api/vehicles/vehicles \
-H "Content-Type: application/json" \
-d '{"type":"SCOOTER","plateNumber":"NYC-001","batteryLevel":95.0}'
# Find nearby vehicles
curl "http://localhost:9000/api/vehicles/vehicles/nearby?latitude=40.7128&longitude=-74.0060&radiusKm=2.0"# Update vehicle location
curl -X POST http://localhost:9000/api/locations/locations/update \
-H "Content-Type: application/json" \
-d '{"vehicleId":"...","latitude":40.7128,"longitude":-74.0060,"speed":15.5,"batteryLevel":90.0}'
# Query nearby
curl "http://localhost:9000/api/locations/locations/nearby?latitude=40.7128&longitude=-74.0060"# Request a ride
curl -X POST http://localhost:9000/api/rides/rides/request \
-H "Content-Type: application/json" \
-d '{"userId":"...","vehicleId":"...","pickupLatitude":40.7128,"pickupLongitude":-74.0060}'
# Start ride
curl -X POST http://localhost:9000/api/rides/rides/{rideId}/start -H "X-User-Id: {userId}"
# Complete ride
curl -X POST http://localhost:9000/api/rides/rides/{rideId}/complete -H "X-User-Id: {userId}"# Process payment
curl -X POST http://localhost:9000/api/payments/payments/process \
-H "Content-Type: application/json" \
-d '{"rideId":"...","userId":"...","amount":12.50,"method":"WALLET"}'
# Refund
curl -X POST http://localhost:9000/api/payments/payments/{paymentId}/refundSharedMobility/
├── pom.xml # Parent POM
├── docker-compose.yml # Infrastructure
├── SPEC.md # Architecture spec
├── common-lib/ # Shared DTOs, exceptions, utilities
├── grpc-contracts/ # .proto definitions + generated stubs
├── service-registry/ # Eureka Server
├── api-gateway/ # Spring Cloud Gateway
├── user-service/ # User management + JWT auth
├── vehicle-service/ # Vehicle CRUD + gRPC server
├── location-service/ # GeoHash index + Kafka consumer
├── ride-service/ # Ride lifecycle
└── payment-service/ # Payment processing
| Metric | Target |
|---|---|
| Nearest vehicle query P99 | < 30ms |
| GPS E2E latency P99 | < 20ms |
| Throughput | 50K vehicles @ 30s interval |
| gRPC call P99 | < 10ms |
This was developed as a course project (Team of 4, Jan-Apr 2026) demonstrating:
- Decomposition of a monolithic application into microservices
- Geo-spatial indexing with Redis GeoHash (precision-7 + overlapping grids)
- Async event-driven architecture with Kafka
- gRPC for internal service contracts
- REST APIs exposed through a unified gateway