Parking Service at Scale

📋 Jump to Takeaways

A parking service manages parking lots, tracking spot availability in real-time, allowing reservations, handling entry/exit, and processing payments. The challenges are real-time occupancy tracking across thousands of lots, handling concurrent spot claims, and dynamic pricing based on demand.

Step 1: Parking Service Requirements

Parking Service Functional Requirements

  • Search for available parking near a location
  • View real-time spot availability per lot
  • Reserve a spot in advance (optional, time-limited hold)
  • Entry/exit detection (license plate or ticket)
  • Automatic billing based on duration and rate
  • Support multiple spot types (regular, handicap, EV charging, compact)

Parking Service Non-Functional Requirements

Metric Target
Lots managed 50,000 parking lots
Total spots 10 million spots (avg 200 per lot, mix of small street lots and large garages)
Peak concurrent users 100K searching simultaneously
Availability updates Real-time (within 2 seconds of car entering/exiting)
Reservation consistency No double-booking of a specific spot
Uptime 99.9%

Step 2: Parking Service Estimation

Notification Traffic

  • Entry/exit events: 10M spots × avg 3 turnovers/day = 30M events/day = ~350 events/sec
  • Search queries: 100K peak concurrent × 1 query/30sec = ~3,300 queries/sec
  • Reservations: ~50K/day = negligible QPS

Parking Service Storage

  • Lot metadata: 50K lots × 5 KB = 250 MB
  • Spot records: 10M spots × 200 bytes = 2 GB
  • Active sessions: 10M × 100 bytes = 1 GB
  • Transaction history: 30M/day × 500 bytes × 365 days = 5.5 TB/year

Bandwidth

  • Search responses (nearby lots + availability): 3,300/sec × 2 KB = 6.6 MB/sec
  • Entry/exit events: 350/sec × 200 bytes = 70 KB/sec (trivial)

Step 3: Parking Service High-Level Design

┌─────────────────────────────────────────────────────────────────────┐
│                        PARKING SERVICE                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ┌──────────┐     ┌──────────────┐     ┌──────────────────┐         │
│  │  Mobile  │────►│  API Gateway │────►│  Search Service  │         │
│  │  App     │     │              │     │  (find nearby    │         │
│  └──────────┘     └──────┬───────┘     │   lots + avail.) │         │
│                          │             └────────┬─────────┘         │
│                          │                      │                   │
│                          │                      ▼                   │
│                          │             ┌──────────────────┐         │
│                          │             │  Geospatial DB   │         │
│                          │             │  (PostGIS/Redis) │         │
│                          │             └──────────────────┘         │
│                          │                                          │
│                          ▼                                          │
│                   ┌──────────────┐                                  │
│                   │  Reservation │                                  │
│                   │  Service     │                                  │
│                   └──────┬───────┘                                  │
│                          │                                          │
│  ┌──────────────┐        ▼                                          │
│  │  IoT Sensors │  ┌──────────────┐     ┌──────────────────┐        │
│  │  / Cameras   │─►│  Occupancy   │────►│  Availability    │        │
│  │  (entry/exit)│  │  Service     │     │  Cache (Redis)   │        │
│  └──────────────┘  └──────┬───────┘     │  lot→free_count  │        │
│                           │             └──────────────────┘        │
│                           ▼                                         │
│                    ┌──────────────┐     ┌──────────────────┐        │
│                    │  Billing     │────►│  Payment         │        │
│                    │  Service     │     │  Gateway         │        │
│                    │  (duration   │     │  (Stripe)        │        │
│                    │   × rate)    │     └──────────────────┘        │
│                    └──────────────┘                                 │
└─────────────────────────────────────────────────────────────────────┘

Entry/exit flow:

Car enters → sensor/camera detects → Occupancy Service:
  1. Decrement available count in Redis
  2. Create active session (lot, spot, plate, entry_time)
  3. Update Availability Cache

Car exits → sensor detects → Occupancy Service:
  1. Increment available count in Redis
  2. Close session (set exit_time)
  3. Billing Service: calculate charge (duration × rate)
  4. Payment Gateway: charge card on file

Step 4: Parking Service Deep Dive

Occupancy Tracking

Each lot has a real-time counter in Redis:

lot:{lot_id}:available:regular    → 45
lot:{lot_id}:available:handicap   → 3
lot:{lot_id}:available:ev         → 8
lot:{lot_id}:available:compact    → 12

Entry event:

DECR lot:{lot_id}:available:{type}

If result < 0 → lot is full for that type, INCR back and reject (or direct to another type).

Exit event:

INCR lot:{lot_id}:available:{type}

Why Redis counters? Atomic, sub-millisecond, handles concurrent entry/exit without locks. The counter is the real-time view; PostgreSQL stores the session history.

Spot-Level vs Lot-Level Tracking

Lot-level (simpler): Just track total available per type. Car gets any open spot. Works for most garages.

Spot-level (complex): Track each individual spot. Required when:

  • Users reserve a specific spot
  • Spots have different rates (premium location)
  • Guidance systems direct cars to specific spots

For spot-level, use a bitmap in Redis:

lot:{lot_id}:spots → 1110010011... (1=occupied, 0=free)

Search Service (Find Nearby Parking)

User opens app → "Find parking near me":

  1. Geospatial query: Find lots within radius using PostGIS or Redis GEO
    GEOSEARCH lots FROMLONLAT -73.98 40.75 BYRADIUS 1 km ASC
  2. Filter: Only lots with available spots of the needed type
  3. Rank: By distance, price, rating, availability percentage
  4. Return: List with real-time availability counts

Caching: Availability counts cached with 2-second TTL. Acceptable staleness, since the exact check happens at entry.

Reservation System

Optional pre-booking (e.g., airport parking):

Reserve → Reservation Service:
  1. Check availability (Redis counter > 0)
  2. DECR counter (hold the spot)
  3. Store reservation (lot, type, user, start_time, end_time)
  4. Set TTL: if user doesn't arrive within 30 min of start_time, release

User arrives → match reservation by plate/QR → confirm entry
User no-show → TTL expires → INCR counter back → charge no-show fee

Overbooking strategy: For large lots (500+ spots), allow 5-10% overbooking on reservations. Statistically, not all reservations convert to arrivals.

Dynamic Pricing

Adjust rates based on demand:

Pricing factors:
  - Current occupancy percentage (>80% → surge)
  - Time of day (peak hours cost more)
  - Day of week (weekday vs weekend)
  - Nearby events (concert at venue → 2× rate)
  - Historical demand patterns

Price tiers:
  0-50% full:  base rate ($3/hr)
  50-80% full: 1.5× ($4.50/hr)
  80-95% full: 2× ($6/hr)
  95-100% full: 3× ($9/hr)

Prices update every 5 minutes based on current occupancy. Displayed in search results so users can compare.

Billing Service

Calculate charges on exit:

Session:
  entry_time: 2026-05-26 09:15
  exit_time:  2026-05-26 14:45
  duration:   5.5 hours

Rate schedule for this lot:
  first_hour: $5
  additional_hours: $3/hr
  daily_max: $25

Charge: $5 + (4.5 × $3) = $18.50 (under daily max)

Pre-authorized payment: Charge card on file at exit. If no card → license plate flagged, invoice mailed.

Fault Tolerance

  • Sensor failure: If entry sensor fails, fall back to camera + license plate recognition. If both fail, manual attendant mode.
  • Redis failure: Counters reconstructed from active sessions in PostgreSQL. Brief inconsistency (seconds) is acceptable.
  • Network partition between sensor and service: Buffer events locally at the lot controller, replay when connection restores.

Key Takeaways

  • Redis atomic counters are the core primitive for availability

    INCR/DECR on lot-level counters handles concurrent entry/exit without locks. Sub-millisecond latency means real-time availability updates. PostgreSQL stores durable session history.

  • Lot-level tracking is sufficient for most use cases

    Individual spot tracking adds complexity (bitmaps, guidance systems) and is only needed for reserved-spot or premium-location scenarios. Start with lot-level counters.

  • Geospatial indexing enables "parking near me"

    PostGIS or Redis GEO finds lots within radius efficiently. Combine with real-time availability filtering and price/distance ranking for useful search results.

  • Reservations need TTL-based release for no-shows

    A reserved spot that nobody claims wastes inventory. Auto-release after a grace period (30 min past start time) keeps availability accurate. Charge a no-show fee to discourage abuse.

  • Dynamic pricing balances supply and demand

    Surge pricing when lots are >80% full incentivizes users to park elsewhere or use transit. Update prices every few minutes based on current occupancy, not faster (confusing UX).

  • Sensor redundancy prevents revenue loss

    A broken entry sensor means cars enter without being tracked (lost revenue). Layer camera + LPR + manual fallback. Buffer events locally during network outages and replay on reconnection.

© 2026 ByteLearn.dev. Free courses for developers. · Privacy