1000 slots x (1 id + 1 type + 1 floor + 1 number) = 4000 bytes
asumming 1 hour mining reservation:
1000 slots x 24 reservations x (1 byte from + 1 byte to + confirmed 1 bit ) = 52000 bytes
52 kylobytes database
GET /user/me/reservations/ - get my reservations
PUT /reservations/preview - get price preview and timeslots
PUT /reservations/ - create slot reservation
PUT /reservations/{uuid}/confirmation - confirm after pay
GET /reservations/{uuid} - find out status of reservation
POST /reservations/{uuid}/cancelation - cancel reservation (if before started)
POST /reservations/{uuid}/check-in
POST /reservations/{uuid}/check-out
Client goes to API using fronted app (web).
He tries to make a reservation, using PUT reservations/preview, which uses cache to find best suitable slot (cache probably looks like time slots mapped to available slots for that time, precalculated for reasonable time, maybe two weeks), and goes to pricing to find cached price.
Then he tries to make a reservation using PUT /reservations/, reservations is created, robust price is calculated (without cache) and he is redirected to payment system.
After payment system we recieve callback to /reservations/{uuid}/confirmation, which marks reservation as paid. And the slot removed from timeslot cache.
Then person comes and checks in. If he leaves early, he might get some refund. When he leaves he checks out.
Load balancer and database sharding are present, but not reflected in schema as it's a standard approach. Kubernetes (if used) or cloud technologies might be used to scale up during spikes.
flowchart TD
B[frontend] --> S{Slots Service}
S --> P{Pricing Service}
P --> PC[prcing cache]
S --> D[Database]
S --> RS[Reservation Cache]
I would use SQL database for better consistency + nosql cache
pricing cache:
[slot_type,timeofday] => price in usd
reservationa cache:
[slot_type,from,to] => [] array of slots
database:
User:
id
Vehicle:
id
type
SlotMetadata:
id
type
floor
number
Reservations:
id
user_id
vehicle_id
from
to
confirmed
I would add sharding by SlotId.
erDiagram
USER }|..|{ VEHICLE : has
USER ||--o{ RESERVATION : make
SLOT }|..|{ RESERVATION:has
RESERVATION }|..|{ VEHICLE:has
At the begining pricing service will just calculate price based of slot_type and time slot (evening could be pricier, long stay with multple slots could be cheaper + promo). It will cache prices after calculation.
Reservation service will use reservations cache until creating actual reservation, but will calculate actual timeslots when creating reservation. Removing slots from reservations cache could be done in asynchronous task to not block user.
request flow were described in High-Level Design
Within a single DB transaction, re-check availability for the exact time window, then insert the reservation. If the insert conflicts (violates a unique constraint on slot_id + time_range), rollback and return an error. This way, the check and commit are atomic — no TOCTOU race.