Airbnb Booking System Design

A vacation-rental booking platform matches a guest searching for an accommodation against a host’s listing for a date range, then atomically reserves the dates, charges the guest, and pays out the host. The architecture is dominated by three concerns: (1) search at scale — a guest’s query mixes location, dates, price, and dozens of amenity filters across millions of listings, and search is the highest-QPS path; (2) calendar correctness — under no circumstances may the same listing be double-booked, even under concurrent reservation attempts from different guests; (3) payments orchestration — a booking must atomically charge the guest’s card, hold the funds in escrow, notify the host, and (much later, after check-in) release payout, all across a service mesh that spans many independent backends. Airbnb has published extensively at KDD on its search ranking and personalization (Grbovic & Cheng 2018; Haldar et al. 2019), and on its engineering blog about scaling its payments platform. The same blueprint applies to VRBO, Booking.com, and Expedia, with differences mostly in inventory ownership (Airbnb’s hosts are individuals; Booking.com aggregates hotels via a Channel Manager API).

1. Requirements

Functional Requirements

  • Listing browsing and search. A guest searches by destination, check-in/check-out dates, number of guests, and any subset of ~50 filters (price range, room type, amenities such as Wi-Fi/pool/kitchen, instant-book flag, language of host, neighborhood). Results return paginated, ranked, with map view and list view.
  • Listing detail page. Photos, description, amenities, calendar availability, host profile, reviews, location map, price breakdown for the selected dates, “book” or “request to book” button.
  • Booking flow. Guest selects dates → reviews price including taxes/fees → enters payment → confirms. The system must atomically: lock the dates, charge the payment method (or hold), notify the host, send confirmation. If the host has not enabled “instant book,” the booking is a request awaiting host accept/decline within 24 hours.
  • Host onboarding. Host creates account, lists property, uploads photos, sets calendar, sets pricing rules (base, weekend, season, length-of-stay discounts, cleaning fee), sets house rules.
  • Calendar management. Host can block dates manually or via integration with external channels (Booking.com, VRBO sync). The platform’s calendar must reflect both internal bookings and external blocks.
  • Messaging. Pre-booking and during-stay messaging between guest and host, with the platform proxying contact info to prevent off-platform circumvention until booking is confirmed.
  • Reviews. After checkout, both parties write reviews (revealed simultaneously after both submit, or after a deadline, to reduce retaliation bias).
  • Dynamic pricing recommendations. The platform suggests prices to hosts based on demand, comparable listings, and seasonality (Airbnb’s “Smart Pricing” feature).
  • Trust and safety. Identity verification, fraud screening on payments, review spam detection, anti-discrimination enforcement.

Non-Functional Requirements

  • Scale. Airbnb has reported >100M users worldwide and ~7M listings as of 2023; on a peak day, there are tens of millions of search queries.
  • Search latency. P95 under 500 ms for a result page including ranking, geographic filtering, and personalization.
  • Calendar correctness. Zero double-bookings under any concurrency. This is the single most important consistency requirement.
  • Payment correctness. No double charges for the same booking — Airbnb has a whole engineering post on this.
  • Availability. ≥ 99.95% for search, ≥ 99.99% for the booking-creation path.
  • Geo-distribution. Multi-region; primary write region and read replicas/edge caches.
  • Internationalization. Currency, language, address formats, regulatory tax rules, payout corridors.

2. Capacity Estimation

  • Listings: ~7 million active. Each listing’s full detail page (photos, description, amenities) ≈ ~10 KB of text/structured data plus 5–30 photos at ~500 KB each → ~5 MB per listing total. 7M × 5 MB ≈ 35 TB total photo storage (in a CDN-fronted object store like S3); text metadata ~70 GB, fits in a single relational shard.
  • Calendar (per-listing per-day): 7M listings × 365 days/year × 2 years roll-forward = 5.1 billion rows. At ~50 B per row (listing_id, date, status, price, source) ≈ 250 GB. Easily sharded by listing_id.
  • Daily search QPS: Tens of millions of searches per day. Assume 50M queries/day → ~600 QPS average, peak ~5K QPS.
  • Daily bookings: ~1M per day at peak season. ~12 bookings/s, peak ~50/s.
  • Booking record: ~3 KB per booking (guest, listing, dates, price, taxes, payment refs, status, messages thread pointer). 1M/day × 3 KB ≈ 3 GB/day, ~1 TB/year — tiny.
  • Photo bandwidth: With CDN cache hit rate >95%, origin pull is small; CDN egress is the dominant cost — easily petabytes/month for a service this size.
  • Search index size: Listings × inverted index (text + numeric + geo) ≈ ~100 GB sharded across an Elasticsearch cluster of dozens of nodes.

The dominant infrastructure cost is the search and ranking tier (running ML models per request) and photo CDN egress. The transactional core (booking writes) is small.

3. API

GET    /v1/search/listings
  Query: ?location=&check_in=&check_out=&guests=&filters=
  → 200 { listings: [{id, title, price_breakdown, photos[0:3], lat, lng, rating}],
          map_bounds, total_count, next_page_token }

GET    /v1/listings/{listing_id}
  → 200 { id, title, description, photos, amenities, host: {...}, reviews: [...],
          calendar: { available_dates }, pricing_rules, location, house_rules }

GET    /v1/listings/{listing_id}/availability
  Query: ?check_in=&check_out=&guests=
  → 200 { available: bool, total_price, line_items, refundable_until }

POST   /v1/bookings
  Body: { listing_id, check_in, check_out, guests, payment_method_id,
          message_to_host?, idempotency_key }
  → 201 { booking_id, state: pending_host | confirmed,
          total_charged, payment_state }

GET    /v1/bookings/{booking_id}
  → 200 { ..., state, host_response, refund_policy }

POST   /v1/bookings/{booking_id}/cancel
  Body: { reason }
  → 200 { refund_amount, payout_adjustment }

POST   /v1/hosts/{host_id}/listings
  Body: { title, location, photos, amenities, price, calendar }
  → 201 { listing_id }

POST   /v1/listings/{listing_id}/calendar
  Body: { dates_to_block: [...], dates_to_unblock: [...] }
  → 200

POST   /v1/messages
  Body: { thread_id, body }
  → 201

POST   /v1/bookings/{booking_id}/review
  Body: { stars, public_review, private_feedback }
  → 200

4. Data Model

4.1 Listings, Photos, Amenities

listings:
  listing_id      BIGINT PK
  host_id         BIGINT INDEX
  title           TEXT
  description     TEXT     (long-form)
  lat, lng        DECIMAL
  geo_h3_cell     BIGINT   INDEX
  city, country, neighborhood    (denormalized for filters)
  property_type   ENUM     (entire_place, private_room, shared_room)
  bedrooms, beds, bathrooms      INT
  max_guests      INT
  base_price      DECIMAL
  cleaning_fee    DECIMAL
  pricing_rules   JSON     (weekend, seasonal, LOS discounts)
  amenities       JSON     (set of amenity IDs)
  rating          DECIMAL  (denormalized aggregate)
  review_count    INT
  status          ENUM     (active, snoozed, removed)
  created_at, updated_at

listing_photos:
  photo_id, listing_id, ordering, s3_key, alt_text

amenities_dictionary:   (controlled vocab — wifi, pool, kitchen, ...)

4.2 Calendar (per-listing per-day)

listing_calendar:
  listing_id  BIGINT
  date        DATE
  state       ENUM (available, blocked, booked, external_blocked)
  price       DECIMAL    (effective price for this specific date)
  booking_id  BIGINT NULL (when state=booked)
  PRIMARY KEY (listing_id, date)

Sharded by listing_id (each listing’s calendar lives on one shard, cheap to lock during a booking transaction). The composite primary key gives instant lookup for any (listing, date) pair, and a range scan for a date range. This single table is the heart of the consistency story — it’s where the no-double-booking invariant is enforced.

4.3 Bookings

bookings:
  booking_id        BIGINT PK
  listing_id        BIGINT INDEX
  guest_id          BIGINT INDEX
  host_id           BIGINT INDEX
  check_in, check_out  DATE
  guests            INT
  state             ENUM (pending_host, confirmed, canceled, completed)
  total_amount      DECIMAL
  currency          CHAR(3)
  payment_method_ref TEXT    (PSP token)
  payment_state     ENUM (held, captured, refunded)
  payout_state      ENUM (pending, released, withheld)
  idempotency_key   UUID UNIQUE
  created_at, updated_at, confirmed_at, canceled_at

4.4 Search Index (Inverted, ES-backed)

A document per listing flattens listing fields + amenities + denormalized host/rating/review_count for filtering and ranking. Updated via Kafka Inverted Index CDC from the OLTP DB so the index lags writes by 1–10 seconds.

4.5 Messaging

message_threads: thread_id, listing_id, guest_id, host_id, last_message_at
messages: message_id, thread_id, sender_id, body, created_at

Sharded by thread_id. Pre-booking, contact info (phone, email) is regex-stripped to keep transactions on-platform.

5. High-Level Architecture

flowchart TB
    subgraph Clients
        G[Guest App / Web]
        H[Host App / Web]
    end
    subgraph Edge
        APIGW[API Gateway]
        CDN[CDN: photos + static]
    end
    subgraph SearchTier["Search & Discovery"]
        SrchSvc[Search Service]
        Rank[Personalization / Ranking ML]
        ES[(Elasticsearch / Lucene<br/>inverted index)]
    end
    subgraph Listings["Catalog"]
        ListSvc[Listing Service]
        ListDB[(Postgres / sharded)]
        Photos[(S3 / object store)]
    end
    subgraph BookingCore["Booking Core (OLTP)"]
        BookSvc[Booking Service]
        CalDB[(Calendar shards)]
        BookDB[(Booking DB)]
        Saga[Saga Orchestrator]
    end
    subgraph Pay["Payments"]
        PaySvc[Payment Service]
        PSP[(Stripe / Adyen)]
        Escrow[(Escrow ledger)]
    end
    subgraph Trust
        Fraud[Fraud Service]
        IDV[ID Verification]
    end
    subgraph Comms
        Msg[Messaging Service]
        Notif[Notification Service]
    end
    subgraph Async
        Kafka[Kafka]
        Airflow[Airflow DAGs]
        DW[(Data Warehouse)]
    end

    G --> CDN
    G --> APIGW
    H --> APIGW
    APIGW --> SrchSvc
    SrchSvc --> ES
    SrchSvc --> Rank
    APIGW --> ListSvc
    ListSvc --> ListDB
    ListSvc --> Photos
    APIGW --> BookSvc
    BookSvc --> Saga
    Saga --> CalDB
    Saga --> PaySvc
    Saga --> Fraud
    Saga --> Notif
    PaySvc --> PSP
    PaySvc --> Escrow
    APIGW --> Msg
    BookSvc --> Kafka
    ListSvc --> Kafka
    Kafka --> ES
    Kafka --> DW
    Airflow --> DW

What this diagram shows. The discovery path (guest browsing) hits the Search tier (Elasticsearch + ranking), with photos served entirely off the CDN. The booking path goes through a saga orchestrator that drives the multi-step distributed transaction across the calendar shards, the payment service (which calls the third-party PSP and writes the escrow ledger), and the fraud service. The catalog (listings + photos) is its own service. The async pipeline (Kafka + Airflow) keeps the search index in sync with OLTP writes via Change Data Capture (CDC), and feeds the analytics warehouse. Notable: Airflow originated at Airbnb (open-sourced 2015) — it’s the canonical platform for orchestrating data and operational workflows at the company.

6. Request Flow — Guest Books a Listing

sequenceDiagram
    participant G as Guest
    participant GW as API Gateway
    participant Book as Booking Svc
    participant Cal as Calendar Shard
    participant Saga as Saga Orchestrator
    participant Pay as Payment Svc
    participant PSP as Stripe-style PSP
    participant Fraud as Fraud
    participant H as Host (push)
    participant Notif as Notification

    G->>GW: POST /v1/bookings {listing, dates, payment, idempotency_key}
    GW->>Book: create_booking
    Book->>Book: idempotency check (existing booking_id?)
    Book->>Saga: start
    Saga->>Cal: BEGIN; SELECT FOR UPDATE listing_calendar WHERE listing=L AND date IN [c_in..c_out)
    Note over Cal: Rows are locked.
    Cal-->>Saga: states for each date
    alt Any date != available
        Saga-->>G: 409 Conflict (already booked)
    else All available
        Saga->>Fraud: score(guest, payment_method, listing)
        Fraud-->>Saga: ok
        Saga->>Pay: authorize_hold(amount)
        Pay->>PSP: hold(token, amount)
        PSP-->>Pay: hold_id
        Pay-->>Saga: hold_id
        Saga->>Cal: UPDATE state='booked', booking_id=B; COMMIT
        Saga->>Book: state=confirmed (or pending_host)
        Saga->>Notif: notify host + guest
        Saga-->>G: 201 booking confirmed
    end

Reading the sequence. The atomicity hinges on the SELECT FOR UPDATE within the calendar transaction. The sequence locks the relevant per-day rows, verifies all are available, then writes the booking. Because the lock is held until commit, any concurrent attempt to book overlapping dates blocks until the first transaction commits or aborts; on commit, the second attempt sees booked and gets a 409 Conflict. The payment hold happens inside the same saga but typically outside the calendar transaction (because it calls an external service and we don’t want to hold DB locks across a network call to Stripe) — the saga’s compensating action is “void the hold” if any subsequent step fails. Fraud screening can be sync (block bad bookings) or async (post-hoc cancel). For “request to book” listings, the state is pending_host; the host has 24 hours to accept, after which the booking auto-cancels and the hold is released.

7. Deep Dive 1 — Search Ranking and Personalization

Airbnb’s search ranking is the most studied component publicly. The 2018 KDD paper Real-time Personalization using Embeddings for Search Ranking at Airbnb (Grbovic & Cheng) describes a system that:

  1. Trains a listing embedding by Word2Vec-style skip-gram over historical click sessions (treating a sequence of listings clicked in one session as a “sentence”). Listings with similar embeddings tend to attract similar users — geography, amenities, and aesthetic implicitly cluster.
  2. Trains a user-type and listing-type embedding to handle cold-start (new users have no clicks yet, but their inferred type — “frequent business traveler in NYC” — has predictable preferences).
  3. Combines embeddings with hand-crafted features (location match, price match, instant-book, host responsiveness) in a Gradient-Boosted Decision Tree (GBDT) ranker.
  4. Uses real-time signals — the listings the guest has clicked in the current session — to re-rank the next page of results.

The 2019 KDD paper Applying Deep Learning to Airbnb Search (Haldar et al.) describes the migration from GBDT to deep neural networks, with hard-won lessons (a deep model with naive feature engineering underperformed the GBDT until they re-engineered features for the DNN’s strengths). This is one of the more honest industry papers on ML system migration — it documents missteps as well as wins.

Architecture for search query handling:

  1. Geographic prefilter — bounding box of the guest’s map view (or “destination”) narrows candidates from millions to thousands.
  2. Filter prefilter — dates available, num guests, hard amenity filters (kitchen, wifi).
  3. Candidate generation — Elasticsearch’s Inverted Index returns ~1000 candidates ranked by base relevance.
  4. Ranking — the ML model scores all 1000 candidates with personalized features; top 30–50 are returned for the page.
  5. Re-ranking — diversity (don’t show 30 nearly-identical listings) and business rules (deboost hosts with poor recent reviews).

Tail latency budget: 500 ms total. Candidate generation 100 ms, ranking 300 ms, re-ranking + serialization 100 ms. The ranker runs at ~10K QPS at peak — a non-trivial fleet of ML inference servers (TensorFlow Serving or Triton).

8. Deep Dive 2 — Atomic Booking and the Calendar Invariant

The single most asked sub-question: how do you prevent double-bookings? Three patterns commonly proposed:

8.1 Pessimistic Locking (Database Row Locks)

The textbook solution. SELECT ... FOR UPDATE on the per-day calendar rows inside a transaction. Concurrent attempts wait, then see the dates as booked. Pros: simple, correct, well-understood. Cons: lock duration includes any I/O inside the transaction, so doing the payment authorize inside the lock means slow PSP calls block other bookings. Mitigation: do the payment hold outside the lock; only update the calendar once the hold succeeds; use a saga’s compensation to refund if the calendar update fails.

8.2 Optimistic Concurrency Control (Compare-And-Swap)

Read the calendar rows without a lock; on commit, validate that the rows are still in the expected state via a WHERE state='available' predicate or a version column. If validation fails, retry. Pros: shorter lock duration; better throughput in low-conflict scenarios. Cons: under high contention (a hot listing — Taylor Swift’s airbnb during the Eras Tour) you get repeated retry failures and worse latency.

8.3 Distributed Two-Phase Commit

When the calendar shard, payment system, and booking record live in different databases, Two-Phase Commit would atomically commit them all. In practice this is rarely used because: (a) the payment processor is an external SaaS (Stripe) that doesn’t participate in 2PC; (b) 2PC has well-known availability problems (a coordinator crash blocks everyone). The preferred pattern is the saga with idempotency, which gives at-least-once execution with explicit compensations.

Airbnb’s Practical Approach

From their payments post: they use idempotency keys throughout, generated at the API gateway and propagated to every downstream call, so a retry never produces duplicate side-effects. The calendar transaction is short and pessimistic; the payment authorization is wrapped in a saga step with explicit compensate-on-failure (void the hold). Cancellations re-open calendar dates atomically.

The deeper invariant: a booking and its calendar update must be in the same transaction, or neither happens. Anything else allows a window where the calendar shows booked but no booking record exists (or vice versa) — both are user-visible bugs.

9. Deep Dive 3 — Photo Pipeline and CDN

Photos are the hero asset of an Airbnb listing — the click-through rate hinges on the cover photo. Architecturally:

  1. Host uploads photos via direct-to-S3 presigned URLs (the upload bypasses the application server).
  2. An async worker (Airflow-orchestrated or Kafka-consumer) generates multiple resolutions — thumbnail, mobile, retina, full — and possibly applies smart cropping (face/object detection to avoid awkward crops at smaller aspect ratios).
  3. All variants live in S3 behind the CDN.
  4. The listing detail page references variants by S3 key + resolution; the CDN handles caching geographically.
  5. ML models analyze photos for quality scoring (lighting, composition, room category) and feed back into the ranking model — high-quality photos boost ranking.

For 7M listings × ~20 photos × ~5 variants = ~700M objects, ~30+ TB of binary data with massive read fan-out. CDN cache hit rate is the dominant operational lever.

10. Scaling

10.1 Search Tier — Elasticsearch Sharding

Listings are sharded across an Elasticsearch cluster (typically by random hash of listing_id, or by region). Replication factor 2–3 for read availability and tail-latency hedging. For geo queries, ES’s native geo-point index (a Quadtree-like structure) handles bounding-box and within-radius filters efficiently.

10.2 Calendar Sharding

Sharded by listing_id: each listing’s full calendar lives on one shard. Cross-listing aggregations (e.g., “occupancy in Paris this weekend”) run async via Kafka → analytics. The advantage: a booking transaction touches at most one shard.

10.3 Geo-Distribution

Reads can be served from regional read replicas with eventual consistency; writes funnel to a primary region. Booking creation must hit the primary; search reads from the closest region’s replica. For users searching while traveling, the cross-region read latency from the primary region is 50–200 ms — acceptable for browsing, but during checkout the system pins to the primary region for the calendar transaction.

10.4 Payments

The Payment Service is itself sharded — one logical PSP integration but a fleet of services balancing across multiple PSPs (Stripe, Adyen, Braintree) for redundancy and for region-specific corridor support (China requires Alipay, etc.). The escrow ledger is double-entry bookkeeping in a strongly-consistent DB.

10.5 Async Pipeline — Airflow’s Origin

Apache Airflow was created at Airbnb (Maxime Beauchemin, ~2014, open-sourced 2015) to orchestrate ETL DAGs. It now runs hundreds of thousands of pipeline jobs across Airbnb’s data platform — from search-index rebuilds to fraud-model training to financial reconciliation. See Distributed Task Scheduler System Design.

11. Real-World Example

Airbnb’s Documented Stack

  • Search: Elasticsearch backbone, ranking with TensorFlow-served deep models. The 2018 and 2019 KDD papers cited above are the most thorough public window.
  • Storage: MySQL primary, sharded for scale; Cassandra and Druid for some workloads; S3 for objects; Redis for hot caches.
  • Payments: Multi-PSP — Stripe historically, plus regional providers; double-entry escrow ledger; comprehensive idempotency key propagation.
  • Workflows: Airflow for batch DAGs; Cadence/Temporal-style for online stateful workflows.
  • Service mesh: SmartStack (open-sourced) was Airbnb’s internal service-discovery / health-check system for many years; later supplemented by Envoy / Istio.
  • Mobile and web stacks: Substantially React-based on web; native iOS/Android.
  • Streaming: Kafka for event distribution.
  • Trust and Safety: ML-based fraud scoring on bookings; identity verification through automated and manual review.

Comparable Platforms

  • VRBO / Booking.com: Both aggregate hotel inventory via Channel Manager APIs (SiteMinder, Cloudbeds) rather than per-host management. The booking model is similar but the inventory is hierarchical (hotel → room type → individual rooms).
  • Vrbo specifically is owner-side similar to Airbnb (whole-home rentals).

12. Tradeoffs

DecisionOption AOption BWhen to pick AWhen to pick B
Calendar concurrencyPessimistic SELECT FOR UPDATEOptimistic CAS retryHigh contention (hot listings)Low contention, high throughput
Distributed txnTwo-Phase CommitSaga + compensationsSingle DB, tightly coupledMulti-service, heterogeneous (incl. external PSP)
Search backendPostgres full-textElasticsearchSmall catalog (<1M)Multi-million catalog with rich filters
Ranking modelGBDT (XGBoost / LightGBM)Deep NNTabular features dominateLarge interaction features, embeddings
Photo storageDB BLOBsObject store + CDNToy scaleProduction scale (always B)
Geo replicationSingle-region writesMulti-region active-activeStrong consistency simplerLatency requires it (rarely Airbnb-scale)
Booking flowInstant bookRequest-to-bookMarketplace velocityHost control over guests
Workflow engineCron + scriptsAirflow (or similar)< 10 jobsHundreds of inter-dependent jobs

13. Pitfalls

  1. Allowing payment authorize inside the calendar lock. The PSP roundtrip can be 500–1500 ms; holding a row lock during that time crushes throughput on hot listings.
  2. No idempotency on POST /v1/bookings. A user double-tapping “Confirm” or a network retry creates two bookings. Always require client-supplied idempotency_key and dedupe at the API edge.
  3. Treating calendar as eventually-consistent. It cannot be. The calendar shard is the consistency boundary; even a 1-second staleness allows double-bookings.
  4. Ranking-only-by-distance. A naively distance-ranked search shows the closest crap before far-away gems; without quality and personalization, conversion plummets.
  5. No photo pre-warming on listing publish. A host publishes a listing, immediately gets traffic, and their photos miss the CDN — slow first-impression. Pre-warm by issuing dummy CDN GETs at listing-publish time.
  6. Relying on external Channel Manager being live. For aggregator platforms, the upstream availability feed lags reality; mitigations include re-validating availability at booking time even if the search said available.
  7. Letting search index lag too far. A guest searches, finds a listing, the host had just removed it — a confusing experience. CDC pipelines need <10s lag.
  8. Cross-currency reconciliation drift. A guest pays in EUR; host paid in USD; PSP records in their own currency — small FX drift compounds across millions of bookings without a strict reconciliation process.
  9. Ignoring host-side calendar churn. Hosts manually block dates often (personal use, maintenance). The system must accept manual blocks and propagate to search index quickly.
  10. Treating reviews as immediate. Allowing reviews to publish at any time creates retaliation dynamics — Airbnb’s policy is dual-blind: both reviews are hidden until both submitted (or 14 days elapse). This requires holding-and-revealing logic in the review pipeline.

14. Common Interview Variants

  • “Design Airbnb.” Canonical prompt, covering search ranking, calendar invariants, payments saga.
  • “Design Booking.com / Expedia.” Hotel aggregator — focus on Channel Manager integration, multi-room-type inventory, dynamic re-pricing.
  • “Design a movie ticket booking system.” Subset — seats are the analog of dates, but with finer-grained per-show inventory; high contention on opening nights. See also Ticketmaster Booking System Design.
  • “Design OpenTable / restaurant reservations.” Lower-stakes; calendar is per-table per-time-slot.
  • “Design a hotel search engine.” Pure discovery, no inventory — focus on ranking, multi-source aggregation, freshness.
  • “Design a vacation marketplace with last-minute deals.” Adds expiring inventory; pushes auctions/dynamic pricing to the front.

15. Open Questions

  • At the scale Airbnb operates, how much of the personalization signal comes from real-time session behavior vs from longer-term user profiles? The 2018 paper describes both but doesn’t quantify the relative impact.
  • How does Airbnb’s payments platform reconcile with non-Stripe corridors (e.g., China, India, Russia historically)? Are these sagas substantially different per region?
  • How is the search index synchronized when a host edits availability — sub-second visibility seems a hard requirement, but Elasticsearch’s near-real-time refresh interval is typically 1 s.
  • What’s the mitigation when a hot listing (a viral one) overwhelms a single calendar shard? Is there any read-replica fanout for the per-day rows, or is it pure pessimistic-lock contention?

16. See Also