PracHub
QuestionsLearningGuidesInterview Prep
|Home/System Design/Moveworks

Design a car rental booking system

Last updated: Jun 24, 2026

Quick Overview

This question evaluates understanding of system design competencies including scalability, data modeling, API design, concurrency control, transactional integrity, and caching for a time-based booking domain.

  • medium
  • Moveworks
  • System Design
  • Software Engineer

Design a car rental booking system

Company: Moveworks

Role: Software Engineer

Category: System Design

Difficulty: medium

Interview Round: Onsite

## System Design: Car Rental Booking System Design an online car rental system (like Hertz or Avis) that lets users **search** for available rental cars, get a **price quote**, **book** a car, and later **cancel or modify** the reservation. The core user flows you must support: 1. **Search** for available cars by pickup location, a `[pickup, return)` date/time window, car class (economy/SUV/etc.), and optional filters (price, seats, transmission). 2. **Quote** a total price (base rate + fees + taxes + add-ons). 3. **Book** a car for the selected window. 4. **Cancel or modify** an existing reservation (change dates, class, or location). The single hardest requirement is correctness under concurrency: the same physical car must **never** be double-booked for two overlapping time ranges, even when many users try to book it at the same instant during a promotion. At the same time, search is extremely read-heavy and bursty, and must stay fast. ```hint Where to start Separate the two pressures into two different paths. **Booking** is the *correctness* problem — it needs a strongly consistent write. **Search** is the *scale* problem — it is read-heavy and can tolerate slightly stale data. Designing them as one path forces you to either over-serialize search or under-protect booking. ``` ```hint The core race The double-booking bug is a classic read-then-write race: two requests both "check availability" (see the slot free), then both "insert a reservation." The fix is to make the *overlap check* and the *reservation write* a **single atomic operation** — never two separate round trips. Think about which database primitive can express "no two active reservations for this car may overlap in time" as an invariant the engine enforces (range/interval exclusion, pessimistic row lock + overlap check, or optimistic CAS). ``` ```hint Holds vs. payment Payment is a slow external call (seconds). You cannot hold a DB transaction open across it. Introduce a short-lived intermediate **HELD** state with a TTL that reserves the slot *before* payment, then run the payment as a saga that flips HELD → CONFIRMED or releases it. This also tells you how to make retries safe (idempotency keys). ``` ```hint Search at scale Don't range-scan the live `reservations` table on every search — that couples read load to the write path. Maintain a derived, eventually-consistent **availability projection** fed by reservation events, and re-validate the truth transactionally only at booking time. Note the trap: a per-day "available count" cannot answer a contiguous *multi-day* window correctly — model **busy intervals**, not per-day scalars. ``` ### Constraints & Assumptions State and use scale numbers like these (illustrative — you may pick your own reasonable defaults and justify them): - **Fleet:** a large operator, e.g. ~2,000 locations × ~200 cars ≈ a few hundred thousand cars. Each car belongs to exactly one location. - **Booking write volume is small:** even tens of millions of bookings/year is only single-digit writes/sec average, low hundreds/sec at promotional peak. - **Search is the scaling problem:** read:write skew on the order of 1000:1 → tens of thousands of search QPS at peak. - **Latency targets:** search p95 in the low hundreds of ms; booking may take a few seconds because it involves a payment call. - **A reservation is a half-open interval $[\text{pickup}, \text{return})$** with timezone-aware timestamps; store time in UTC, keep each location's IANA timezone for display and billing math. - **Consistency stance:** booking must be strongly consistent (no double-booking, ever); search may serve slightly stale availability as long as booking re-validates transactionally. A rare false "unavailable" under contention is acceptable; a double-booking is not. ### Clarifying Questions to Ask - Do customers book a **specific car (VIN)** or a **car class** (any car in that class at the location)? This heavily affects the concurrency-control strategy. - What is the database engine of record — does it support range/interval **exclusion constraints** (Postgres) or must the design work on MySQL too? - What are the **cancellation and refund** rules, and is there a free-cancellation window? - Is **pricing dynamic** (surge/seasonal) or are rate plans relatively static? Must the quoted price be locked for the duration of the booking flow? - What is the expected **promotion spike** magnitude, and which locations/classes get hot? - Are **partial-day / hourly** rentals supported, or whole-day only? How is a day that spans a DST transition billed? ### What a Strong Answer Covers A strong answer addresses the following dimensions (these are the things the interviewer is listening for, not the answers themselves): - **Requirements split & key tradeoff:** explicitly separating the strongly-consistent booking path from the eventually-consistent search path, and naming staleness-vs-correctness as the central tradeoff. - **Rough sizing:** back-of-envelope numbers that justify "booking writes are small, search reads are the scale challenge," and therefore the data-store choice. - **Data model:** locations, cars, car classes, rate plans, reservations (with the time interval), payments — and where the no-double-booking invariant lives. - **High-level architecture:** stateless search service, a single booking system-of-record, pricing, payment, an event bus, and a derived availability projection. - **APIs:** search, quote, hold, confirm, modify, cancel — with idempotency on the mutating endpoints. - **Concurrency control:** an atomic check-and-insert via exclusion constraint, pessimistic locking, or optimistic CAS — and why a read-then-write split is wrong; class-level retry to spread contention. - **Hold + payment saga:** a short-lived HELD state with TTL so the slow PSP call never holds a DB transaction; idempotency keys for retry-safety. - **Search/availability scaling:** an interval-aware projection (busy intervals, not per-day counts) served from cache/index, re-validated at booking time. - **Reliability & edge cases:** hold expiry sweeper, the self-overlap subtlety in *modify*, refunds, time zones/DST, and observability metrics. - **Bottlenecks & scaling plan:** hot-class contention, projection staleness, PSP latency — and how each is mitigated. ### Follow-up Questions - How exactly do you implement **modify** when a user extends the return date on the *same* car, so the new window overlaps their own still-active reservation? (Why does a naïve "insert new window first" fail, and what are two correct approaches?) - If the database of record were **MySQL** (no `EXCLUDE USING gist`), how would you preserve the same atomic check-and-insert guarantee? - Would you ever use a **Redis distributed lock** for booking? What can it and can it *not* be relied on for? - How would you handle **cross-location one-way rentals** (pick up in city A, drop off in city B) in the data model and availability projection? - A class shows "available" in search but the `hold` fails because someone just took the last car. How do you make this a clean UX rather than an error?

Quick Answer: This question evaluates understanding of system design competencies including scalability, data modeling, API design, concurrency control, transactional integrity, and caching for a time-based booking domain.

|Home/System Design/Moveworks

Design a car rental booking system

Moveworks logo
Moveworks
Dec 15, 2025, 12:00 AM
mediumSoftware EngineerOnsiteSystem Design
68
0

System Design: Car Rental Booking System

Design an online car rental system (like Hertz or Avis) that lets users search for available rental cars, get a price quote, book a car, and later cancel or modify the reservation.

The core user flows you must support:

  1. Search for available cars by pickup location, a [pickup, return) date/time window, car class (economy/SUV/etc.), and optional filters (price, seats, transmission).
  2. Quote a total price (base rate + fees + taxes + add-ons).
  3. Book a car for the selected window.
  4. Cancel or modify an existing reservation (change dates, class, or location).

The single hardest requirement is correctness under concurrency: the same physical car must never be double-booked for two overlapping time ranges, even when many users try to book it at the same instant during a promotion. At the same time, search is extremely read-heavy and bursty, and must stay fast.

Constraints & Assumptions

State and use scale numbers like these (illustrative — you may pick your own reasonable defaults and justify them):

  • Fleet: a large operator, e.g. ~2,000 locations × ~200 cars ≈ a few hundred thousand cars. Each car belongs to exactly one location.
  • Booking write volume is small: even tens of millions of bookings/year is only single-digit writes/sec average, low hundreds/sec at promotional peak.
  • Search is the scaling problem: read:write skew on the order of 1000:1 → tens of thousands of search QPS at peak.
  • Latency targets: search p95 in the low hundreds of ms; booking may take a few seconds because it involves a payment call.
  • A reservation is a half-open interval [pickup,return)[\text{pickup}, \text{return})[pickup,return) with timezone-aware timestamps; store time in UTC, keep each location's IANA timezone for display and billing math.
  • Consistency stance: booking must be strongly consistent (no double-booking, ever); search may serve slightly stale availability as long as booking re-validates transactionally. A rare false "unavailable" under contention is acceptable; a double-booking is not.

Clarifying Questions to Ask Guidance

  • Do customers book a specific car (VIN) or a car class (any car in that class at the location)? This heavily affects the concurrency-control strategy.
  • What is the database engine of record — does it support range/interval exclusion constraints (Postgres) or must the design work on MySQL too?
  • What are the cancellation and refund rules, and is there a free-cancellation window?
  • Is pricing dynamic (surge/seasonal) or are rate plans relatively static? Must the quoted price be locked for the duration of the booking flow?
  • What is the expected promotion spike magnitude, and which locations/classes get hot?
  • Are partial-day / hourly rentals supported, or whole-day only? How is a day that spans a DST transition billed?

What a Strong Answer Covers Guidance

A strong answer addresses the following dimensions (these are the things the interviewer is listening for, not the answers themselves):

  • Requirements split & key tradeoff: explicitly separating the strongly-consistent booking path from the eventually-consistent search path, and naming staleness-vs-correctness as the central tradeoff.
  • Rough sizing: back-of-envelope numbers that justify "booking writes are small, search reads are the scale challenge," and therefore the data-store choice.
  • Data model: locations, cars, car classes, rate plans, reservations (with the time interval), payments — and where the no-double-booking invariant lives.
  • High-level architecture: stateless search service, a single booking system-of-record, pricing, payment, an event bus, and a derived availability projection.
  • APIs: search, quote, hold, confirm, modify, cancel — with idempotency on the mutating endpoints.
  • Concurrency control: an atomic check-and-insert via exclusion constraint, pessimistic locking, or optimistic CAS — and why a read-then-write split is wrong; class-level retry to spread contention.
  • Hold + payment saga: a short-lived HELD state with TTL so the slow PSP call never holds a DB transaction; idempotency keys for retry-safety.
  • Search/availability scaling: an interval-aware projection (busy intervals, not per-day counts) served from cache/index, re-validated at booking time.
  • Reliability & edge cases: hold expiry sweeper, the self-overlap subtlety in modify , refunds, time zones/DST, and observability metrics.
  • Bottlenecks & scaling plan: hot-class contention, projection staleness, PSP latency — and how each is mitigated.

Follow-up Questions Guidance

  • How exactly do you implement modify when a user extends the return date on the same car, so the new window overlaps their own still-active reservation? (Why does a naïve "insert new window first" fail, and what are two correct approaches?)
  • If the database of record were MySQL (no EXCLUDE USING gist ), how would you preserve the same atomic check-and-insert guarantee?
  • Would you ever use a Redis distributed lock for booking? What can it and can it not be relied on for?
  • How would you handle cross-location one-way rentals (pick up in city A, drop off in city B) in the data model and availability projection?
  • A class shows "available" in search but the hold fails because someone just took the last car. How do you make this a clean UX rather than an error?

Submit Your Answer to Earn 20XP

Sign in to leave a comment

Loading comments...

Browse More Questions

More System Design•More Moveworks•More Software Engineer•Moveworks Software Engineer•Moveworks System Design•Software Engineer System Design

Your design canvas — auto-saved

PracHub

Master your tech interviews with 9,000+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • AI Coding Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.