# Low Level Design: Bike and Scooter Sharing System

Source: https://www.techinterview.org/post/3233472751/lld-bike-scooter-sharing/
Updated: 2026-06-30 · techinterview.org

Dockless bike and scooter sharing systems combine IoT device management, real-time fleet tracking, geofencing enforcement, and per-minute billing. The design challenge is managing thousands of physical devices with unreliable cellular connectivity while keeping the user experience instant and the fleet profitable.

## IoT Device Architecture

Each vehicle is an IoT endpoint with the following hardware components:

- **Embedded SIM (eSIM)** with LTE-M or NB-IoT connectivity for low-power wide-area communication.

- **GPS module** for location reporting, with dead reckoning fallback when GPS signal is lost (e.g., in parking garages).

- **BLE lock controller** that accepts lock/unlock commands from the backend and from the user's phone via Bluetooth as a fallback when cellular is unavailable.

- **Accelerometer** for crash detection and theft detection (movement without an active trip).

Vehicles publish telemetry every 30 seconds via **MQTT** to an IoT platform (e.g., AWS IoT Core or a self-hosted EMQX cluster). The telemetry payload includes GPS coordinates, battery_level (percentage), lock_status (locked/unlocked), speed, and a sequence number for gap detection. The IoT platform routes messages to the backend via an internal message bus.

## Vehicle State Machine

Each vehicle has a state managed by the backend: **available → reserved → in_use → maintenance → unavailable**.

State transitions:

- A vehicle moves from available to reserved when a user reserves it in the app; the reservation holds for 10 minutes before expiring back to available.

- It moves from reserved to in_use when the user unlocks it (QR scan or NFC); the backend sends an MQTT unlock command and the vehicle confirms with an unlock event.

- It returns from in_use to available when the user ends the trip, the vehicle locks, and the geofence check passes.

- It goes from in_use to maintenance when an IoT fault code is received or a user reports damage during or after the trip.

- It moves from available to unavailable when the battery is below threshold or by administrative action.

The state is stored in the `vehicles` table with an optimistic lock version. State transitions triggered by IoT events (e.g., unexpected lock) are reconciled against backend state to avoid divergence. If the IoT-reported state contradicts the backend state for more than 60 seconds, an alert is raised for manual review.

## Geofencing

Parking zones are stored as polygon coordinates in a PostGIS table. When a user ends a trip, the vehicle's GPS coordinates are checked against valid parking zone polygons using a **ray-casting algorithm**: a ray from the point in any direction is checked for intersection count with the polygon edges; odd count means inside.

Enforcement rules:

- If the vehicle is outside any valid parking zone, the user cannot end the trip. The app displays the nearest valid zone on the map.

- Certain permit areas (e.g., university campuses, transit hubs) are **mandatory return zones**: vehicles rented from these zones must be returned to the same zone.

- Vehicles found parked outside zones by field teams are flagged and incur a penalty that may be charged to the last rider.

No-parking zones (e.g., parks, highways) are stored separately. Riding into a no-parking zone triggers an in-app warning. Parking in a no-parking zone charges an additional fee and flags the vehicle for repositioning.

## Battery Monitoring

Battery level is reported in each IoT telemetry message. The backend tracks the current level and a time-series of recent readings per vehicle in a time-series database (InfluxDB or TimescaleDB).

Thresholds:

- Below 20%: vehicle shown as "low battery" in the user app with estimated remaining range.

- Below 10%: vehicle flagged as `unavailable` and removed from the bookable fleet. Field team app highlights these vehicles on the map for priority collection.

Predicted range is calculated as: `remaining_range_km = battery_level * historical_wh_per_km_efficiency`, where efficiency is computed from the vehicle's recent trip history segmented by terrain type (flat, hilly) using the route's elevation profile.

For e-scooters with swappable batteries, the field team app shows battery swap priority score combining battery level, vehicle utilization rate, and location demand score.

## Lock and Unlock Mechanism

**Unlock flow:**

- User scans QR code or taps NFC tag on the vehicle.

- App sends unlock request to backend with vehicle_id and user_id.

- Backend validates: user has valid payment method, no outstanding issues, vehicle is available or reserved by this user.

- Backend publishes MQTT unlock command to the vehicle's device topic.

- Vehicle receives command, disengages the lock, and publishes an unlock confirmation event.

- Backend receives confirmation, transitions vehicle to `in_use`, starts trip record.

**Lock flow:**

- User taps "End Trip" in app.

- Backend sends MQTT lock command to vehicle.

- Vehicle engages lock and publishes lock confirmation.

- Backend validates geofence, calculates fare, transitions vehicle to `available`.

**Fallback**: if MQTT command delivery fails (cellular outage), the app uses BLE to send the lock/unlock command directly to the vehicle. The vehicle queues the state change and reports it when connectivity resumes. The backend handles out-of-order event arrival using the sequence number and timestamp in the telemetry payload.

## Fleet Rebalancing

Supply and demand are rarely in equilibrium. The rebalancing system uses heatmaps to direct field team effort:

- The demand heatmap aggregates trip origins by geohash cell over the past 7 days at the same hour of week, smoothed for weather and events.

- The supply heatmap is the current count of available vehicles per geohash cell from the vehicles table.

- The rebalance score per zone is `score = demand_index - supply_index`, normalized. A high positive score means underserved (need more vehicles); a high negative score means oversupplied (pick up vehicles).

Field team members use a dedicated app that shows vehicles to collect (low battery or high-negative-score zones) and target drop zones (high-positive-score). Routes are optimized as a multi-stop pickup/delivery problem solved with a greedy nearest-neighbor heuristic.

Incentivized user rebalancing gives users who end their trip in a designated low-supply zone a credit on their next ride. The credit amount is set dynamically in proportion to the rebalance score of the destination zone.

## Trip Billing

The trip record is created on unlock with `start_time` and `vehicle_id`. `end_time` is set on lock confirmation. The fare calculation:


```
fare = unlock_fee + (rate_per_minute * trip_duration_minutes)
```

A **pause mode** allows users to lock the vehicle temporarily mid-trip (e.g., entering a shop) while keeping the trip active. During pause, the rate is halved. Pause is limited to 20 minutes; beyond that the trip is automatically ended.

Fare is computed at trip end and charged to the payment method on file. If payment fails, the account is suspended until resolved. The fare breakdown (unlock fee, ride time, any geofence penalties) is shown in the receipt.

Promotions (first ride free, monthly passes, employer subsidies) are applied as fare modifiers stored in a promotions table. The billing service evaluates applicable promotions in priority order and applies the best eligible discount.

## Maintenance Workflow

Vehicles enter the maintenance workflow through three paths:

- A user damage report comes from the in-app "Report Problem" flow with a category (flat tire, broken brake, vandalism) and an optional photo.

- IoT fault codes are generated when vehicle diagnostics detect a hardware fault (e.g., lock actuator failure, GPS module error) and include fault codes in telemetry.

- Scheduled maintenance runs on usage-based triggers (e.g., every 500 km or 30 days, whichever comes first).

Any trigger sets `maintenance_needed = true` on the vehicle record and transitions state to `maintenance`. A work order is created in the field team app with fault details, vehicle location, and severity classification. High-severity faults (brake failure, lock malfunction) are escalated with push notification to the on-call field supervisor.

After the field technician marks the work order complete, the vehicle state transitions back to `available`. A post-maintenance checklist confirmation is required before the vehicle re-enters the rentable fleet.

See also: [Uber Interview Guide 2026: Dispatch Systems, Geospatial Algorithms, and Marketplace Engineering](https://www.techinterview.org/post/3233460273/uber-interview-guide-2026-dispatch-systems-geospatial-algorithms-and-marketplace-engineering/)

See also: [Lyft Interview Guide 2026: Rideshare Engineering, Real-Time Dispatch, and Safety Systems](https://www.techinterview.org/post/3233460306/lyft-interview-guide-2026-rideshare-engineering-real-time-dispatch-and-safety-systems/)

See also: [Airbnb Interview Guide 2026: Search Systems, Trust and Safety, and Full-Stack Engineering](https://www.techinterview.org/post/3233460279/airbnb-interview-guide-2026-search-systems-trust-and-safety-and-full-stack-engineering/)
