ShohozParking
A parking availability and reservation platform where the hard problem is concurrency: never selling the same bay twice.
- Stack
- 6 technologies
The problem
What needed solving
Concurrent reservation requests for the same parking bay must resolve to exactly one confirmed booking — a check-then-write in application code cannot guarantee that under real traffic.
My role
Responsibilities
Architecture and implementation: concurrency design for the allocation path, reservation state modelling, caching strategy, and the customer-facing application.
The solution
Architecture summary
Transactional bay allocation with database-level locking and overlap constraints, an explicit reservation state machine, and Redis caching confined to read-heavy availability views.
Case study
In detail
Context
A parking platform looks like a simple CRUD product until two people reserve the last bay in the same second. Everything interesting about the system is in that moment.
Design decisions
Reservations are settled in the database. Bay allocation happens inside a transaction with the appropriate locking, so concurrent requests for the same bay resolve to exactly one winner and one clear rejection. The correctness does not depend on request timing or on an application-level check-then-write.
State transitions are explicit. A reservation moves through held, confirmed, active, completed and cancelled states with defined transitions and timestamps, which makes both the user-facing behaviour and the operational reporting unambiguous.
Availability is cached, allocation is not. Availability views are read-heavy and tolerate short staleness, so they are cached. The allocation path is never served from cache.
Architecture
- Spring Boot transactional services with pessimistic locking on the allocation path
- PostgreSQL with overlap constraints preventing conflicting reservations on a bay
- Redis caching for availability and location listings, invalidated on reservation state change
- Angular front end with location search, availability display and reservation management
Outcomes
What changed
- Double-booking prevented structurally at the database rather than by application-level checks
- Reservation lifecycle made explicit and auditable through defined state transitions
- Availability reads served from cache while the allocation path stays strictly transactional
- Cache invalidation tied to reservation state changes so availability does not drift