1. Requirements

Functional Requirements

Feature Description Priority
Search Listings Search by location, dates, price, amenities, guest count P0
View Listing Details Photos, description, amenities, location, reviews, calendar P0
Book Property Reserve dates, payment processing, instant/request booking P0
Calendar Management Hosts manage availability, pricing, blocked dates, minimum stay P0
Reviews System Two-sided reviews (guest + host), 14-day window after checkout P0
Messaging Host-guest communication, pre-booking inquiries, booking-related P0
Payment Processing Guest pays upfront, host receives payout after check-in P0
Dynamic Pricing Price suggestions based on demand, seasonality, events P1
Cancellation Policy Flexible, moderate, strict policies with refund rules P1

Non-Functional Requirements

Requirement Target Notes
Scale 150M users, 7M listings, 300M nights booked/year ~10K bookings/min peak
Search Latency <200ms p99 Geo + filter search
Booking Availability 99.95% (no double-booking) Strong consistency required
Read:Write Ratio 100:1 Search-heavy, booking rare
Image Storage ~70M images (10 per listing) CDN delivery required
Data Consistency Strong for bookings, eventual for search Prevent overbooking

Back-of-Envelope Estimates

Metric Calculation Result
Daily Active Users 150M total Γ— 10% DAU 15M DAU
Search QPS 15M Γ— 5 searches/day / 86400s ~900 QPS avg, 5K peak
Booking QPS 300M bookings/year / 31.5M sec/year ~10 QPS avg, 100 peak
Storage (Listings) 7M listings Γ— 50KB metadata ~350GB
Storage (Images) 70M images Γ— 500KB ~35TB
Storage (Bookings) 300M bookings Γ— 2KB ~600GB/year
Interview Callout: Clarify booking semantics early: instant booking vs. request-to-book (host approval required). Instant booking needs stronger availability guarantees. Also confirm whether to support hourly rentals (adds complexity to calendar model).

2. High-Level Design

graph TB subgraph "Client Layer" Web[Web App] Mobile[Mobile Apps] end subgraph "API Gateway / Load Balancer" LB[Load Balancer + API Gateway] end subgraph "Application Services" SearchAPI[Search Service] ListingAPI[Listing Service] BookingAPI[Booking Service] UserAPI[User Service] ReviewAPI[Review Service] MessageAPI[Messaging Service] PaymentAPI[Payment Service] PricingAPI[Pricing Service] end subgraph "Data Layer" ListingDB[(Listings DB
Postgres)] BookingDB[(Bookings DB
Postgres)] UserDB[(User DB
Postgres)] CalendarDB[(Calendar DB
Postgres)] ReviewDB[(Review DB
Postgres)] end subgraph "Search Infrastructure" ES[Elasticsearch
Cluster] GeoIndex[Geospatial Index] end subgraph "Caching Layer" Redis[Redis Cache
Listings, Availability] end subgraph "Storage & CDN" S3[Object Storage
Images, Docs] CDN[CDN
Image Delivery] end subgraph "Message Queue" Kafka[Kafka
Events, Analytics] end subgraph "Background Jobs" PricingWorker[Pricing ML Model] SearchIndexer[Search Indexer] NotificationWorker[Notification Worker] end Web --> LB Mobile --> LB LB --> SearchAPI LB --> ListingAPI LB --> BookingAPI LB --> UserAPI LB --> ReviewAPI LB --> MessageAPI LB --> PaymentAPI SearchAPI --> ES SearchAPI --> GeoIndex SearchAPI --> Redis ListingAPI --> ListingDB ListingAPI --> Redis ListingAPI --> S3 BookingAPI --> BookingDB BookingAPI --> CalendarDB BookingAPI --> PaymentAPI BookingAPI --> Redis UserAPI --> UserDB ReviewAPI --> ReviewDB ReviewAPI --> Kafka MessageAPI --> UserDB MessageAPI --> Kafka ListingDB --> Kafka BookingDB --> Kafka Kafka --> SearchIndexer Kafka --> PricingWorker Kafka --> NotificationWorker SearchIndexer --> ES PricingWorker --> PricingAPI PricingAPI --> ListingDB S3 --> CDN

Core Components

Component Responsibility Technology
Search Service Geospatial search, filters, ranking Elasticsearch, Redis
Listing Service CRUD for listings, photos, amenities Postgres, S3, CDN
Booking Service Availability check, reservation, payment coordination Postgres + locks
Calendar Service Availability management, date range queries Postgres (optimized schema)
Payment Service Charge guest, hold funds, pay host Stripe, ledger DB
Review Service Two-sided reviews, fraud detection Postgres, ML fraud model
Messaging Service Host-guest chat, notifications WebSocket, Kafka, Postgres
Pricing Service Dynamic pricing suggestions ML model, batch jobs
Interview Callout: The architecture separates read-heavy (search) from write-heavy (booking) paths. Search uses eventual consistency (Elasticsearch), while booking requires strong consistency (Postgres with locks). Explain this trade-off.

4. Booking Flow

Booking State Machine

State Description Timeout
PENDING User initiated booking, dates reserved (pessimistic lock) 15 minutes
PAYMENT_PROCESSING Payment gateway called, awaiting response 5 minutes
CONFIRMED Payment succeeded, booking finalized -
CANCELLED User or host cancelled, refund issued per policy -
EXPIRED Payment timeout, dates released -

Booking Flow Sequence Diagram

sequenceDiagram participant Guest participant BookingAPI participant CalendarDB participant PaymentAPI participant HostNotification participant Kafka Guest->>BookingAPI: POST /bookings (listing_id, dates, guests) BookingAPI->>CalendarDB: BEGIN TRANSACTION BookingAPI->>CalendarDB: SELECT * FROM calendar WHERE listing_id=X AND dates IN (range) FOR UPDATE alt Dates Available CalendarDB-->>BookingAPI: 0 conflicts BookingAPI->>CalendarDB: INSERT INTO bookings (status=PENDING, expires_at=NOW()+15min) BookingAPI->>CalendarDB: UPDATE calendar SET blocked=TRUE WHERE dates IN (range) BookingAPI->>CalendarDB: COMMIT BookingAPI-->>Guest: 200 OK {booking_id, status=PENDING, expires_at} Guest->>PaymentAPI: POST /payments (booking_id, payment_method) PaymentAPI->>PaymentAPI: Charge card via Stripe alt Payment Success PaymentAPI-->>BookingAPI: Payment succeeded BookingAPI->>CalendarDB: UPDATE bookings SET status=CONFIRMED BookingAPI->>Kafka: Publish BookingConfirmed event Kafka->>HostNotification: Send notification to host Kafka->>SearchIndexer: Update ES (block dates) BookingAPI-->>Guest: 200 OK {status=CONFIRMED} else Payment Failed PaymentAPI-->>BookingAPI: Payment failed BookingAPI->>CalendarDB: DELETE FROM bookings WHERE booking_id=X BookingAPI->>CalendarDB: UPDATE calendar SET blocked=FALSE WHERE dates IN (range) BookingAPI-->>Guest: 400 Payment Failed end else Dates Unavailable CalendarDB-->>BookingAPI: Conflict detected BookingAPI->>CalendarDB: ROLLBACK BookingAPI-->>Guest: 409 Conflict (dates unavailable) end Note over BookingAPI,CalendarDB: Background Job: Expire PENDING bookings after 15min

Double-Booking Prevention

Strategy Mechanism Trade-off
Pessimistic Locking SELECT FOR UPDATE on calendar rows during booking Serializes concurrent bookings (safe but slower)
Unique Constraint UNIQUE(listing_id, date) in calendar table DB-level guarantee against double-booking
Idempotency Key Client sends idempotency_key, server dedupes retries Prevents duplicate bookings from retries
Timeout + Cleanup PENDING bookings expire after 15min, cron releases dates Prevents indefinite holds

Booking API Endpoints

Endpoint Method Description
/bookings POST Create booking (check availability + reserve dates)
/bookings/{id}/confirm POST Finalize booking after payment
/bookings/{id}/cancel POST Cancel booking (refund per policy)
/bookings/{id} GET Get booking details
/users/{id}/bookings GET List user's bookings (guest or host view)
Interview Callout: The 15-minute reservation window is critical. Without it, users could hold dates indefinitely without paying. Implement a background job (cron or TTL index) to auto-expire PENDING bookings and release dates.

5. Calendar & Availability

Calendar Schema

Column Type Description
listing_id UUID Foreign key to listings table
date DATE Single calendar date
status ENUM AVAILABLE, BOOKED, BLOCKED
price DECIMAL Price for this night (dynamic pricing)
booking_id UUID (nullable) Reference to booking if status=BOOKED
min_stay INTEGER Minimum nights required (host-defined)
updated_at TIMESTAMP Last update timestamp

Index Strategy

Index Columns Purpose
PRIMARY KEY (listing_id, date) Enforce unique date per listing, fast lookups
BTREE (listing_id, date, status) Range queries: "check availability for dates X-Y"
BTREE (booking_id) Reverse lookup: find all dates for a booking

Efficient Date Range Queries

Query Type SQL Example Notes
Check Availability SELECT COUNT(*) FROM calendar WHERE listing_id=? AND date BETWEEN ? AND ? AND status='AVAILABLE' Returns 0 if any date unavailable
Block Dates UPDATE calendar SET status='BLOCKED' WHERE listing_id=? AND date BETWEEN ? AND ? Host manually blocks dates
Book Dates UPDATE calendar SET status='BOOKED', booking_id=? WHERE listing_id=? AND date IN (?,...) Atomic update during booking
Get Pricing SELECT date, price FROM calendar WHERE listing_id=? AND date BETWEEN ? AND ? Calculate total cost

Minimum Stay Logic

Scenario Host Rule Validation
Weekend Bookings min_stay=2 on Fri-Sat Reject 1-night Friday bookings
Peak Season min_stay=7 in July/August Enforce weekly rentals during summer
Gap Prevention Don't allow 1-day gaps between bookings Check prev/next bookings, suggest extended stay

Calendar Initialization

Approach Description Trade-off
Pre-populate 2 years Insert 730 rows per listing on creation Simple queries, but 7M listings Γ— 730 = 5B rows
On-demand insertion Only insert dates when booked/blocked Sparse table, but complex "available by default" logic
Hybrid (6-month window) Pre-populate next 6 months, extend on query Balance storage vs. complexity
Interview Callout: The (listing_id, date) primary key enforces uniqueness at the DB level, preventing double-booking even under race conditions. Discuss sharding strategy: shard by listing_id to co-locate all dates for a listing on one shard.

6. Dynamic Pricing

Pricing Factors

Factor Signal Weight
Supply & Demand Available listings vs. search volume in area 40%
Seasonality Peak season (summer, holidays) vs. off-season 25%
Local Events Concerts, conferences, sports (API: Eventbrite, SeatGeek) 20%
Day of Week Weekends more expensive than weekdays 10%
Booking Velocity Recent bookings in area (trending demand) 5%

Pricing Model Architecture

Component Description Technology
Feature Pipeline Aggregate search/booking data by region + date Spark batch jobs (daily)
ML Model Predict optimal price given features (regression) XGBoost, deployed to SageMaker
Pricing Service Serve price suggestions to hosts via API Python Flask + Redis cache
Override Mechanism Host can accept/reject suggestions, set manual prices Calendar table (host has final say)

Price Suggestion Workflow

Step Action Output
1. Feature Extraction Lookup listing location, nearby bookings, events Feature vector: [lat, lng, date, supply, demand, events, ...]
2. Model Inference Call ML model API with features Suggested price: $120/night
3. Host Notification Show suggestion in host dashboard "We recommend $120/night (15% above your base price)"
4. Host Decision Host accepts or sets custom price Update calendar table with final price

Event-Based Pricing Example

Event Location Date Price Multiplier
Super Bowl Phoenix, AZ Feb 2027 3-5x
Coachella Indio, CA April 2027 2-4x
Tech Conference SF, CA Various 1.5-2x
New Year's Eve NYC Dec 31 2-3x

Pricing Constraints

Constraint Rule Reason
Max Increase No more than 2x host's base price Prevent sticker shock, maintain trust
Min Price Never below host's floor price Host profitability
Smoothing Gradual price changes (avoid spikes) User experience
Last-Minute Discount Reduce price if unbooked 3 days before Fill empty dates
Interview Callout: Dynamic pricing is a recommendation system, not enforcement. Hosts must opt-in and can override. This balances algorithmic optimization with host autonomy (critical for marketplace trust).

7. Reviews & Trust

Two-Sided Review System

Aspect Guest Reviews Host Host Reviews Guest
Timing After checkout (14-day window) After checkout (14-day window)
Visibility Public on listing page Public on guest profile (visible to hosts only)
Ratings Cleanliness, accuracy, communication, location, value Cleanliness, communication, house rules
Text Review Optional, 500 char max Optional, 500 char max
Blind Period Reviews hidden until both submit (or 14 days expire) Reviews hidden until both submit (or 14 days expire)

Review Schema

Column Type Description
review_id UUID Primary key
booking_id UUID Foreign key (one review per booking per side)
reviewer_id UUID User who wrote review
reviewee_id UUID User being reviewed
review_type ENUM GUEST_TO_HOST, HOST_TO_GUEST
rating_overall INTEGER (1-5) Overall star rating
rating_cleanliness INTEGER (1-5) Cleanliness score
rating_communication INTEGER (1-5) Communication score
comment TEXT Written feedback
submitted_at TIMESTAMP When review was submitted
published_at TIMESTAMP When review became public (after blind period)
fraud_score FLOAT ML-based fraud detection score (0-1)

Fraud Detection

Signal Red Flag Action
Velocity User submits 10+ reviews in 1 hour Flag for manual review
Text Similarity Review text 90%+ similar to others from same user Likely bot/template
Rating Distribution Listing has 50 reviews, all 5-star Suspiciously uniform
Account Age New account (< 7 days old) leaving reviews Possible fake account
No Booking Review submitted without completed booking Block submission

Review Aggregation

Metric Calculation Usage
Average Rating SUM(rating_overall) / COUNT(*) Displayed on listing page, used in search ranking
Review Count COUNT(*) WHERE published_at IS NOT NULL Trust signal (more reviews = more reliable)
Category Breakdown AVG(rating_cleanliness), AVG(rating_communication), etc. Shown in listing details
Recency Weighting Weight recent reviews 2x older reviews Reflect current listing quality
Interview Callout: The 14-day blind period prevents retaliation. Both parties submit reviews without seeing the other's feedback. Once both submit (or 14 days expire), reviews become public simultaneously. This encourages honest feedback.

8. Messaging System

Messaging Requirements

Feature Description Priority
Pre-Booking Inquiries Guest asks questions before booking P0
Booking Coordination Check-in details, keys, parking, etc. P0
Real-Time Delivery WebSocket for instant messages P0
Push Notifications Mobile push when offline P0
Message History Persist conversation, searchable P0
Automated Responses Host can set auto-replies (FAQ) P1
Translation Auto-translate messages (60+ languages) P1

Messaging Architecture

Component Technology Purpose
WebSocket Server Node.js + Socket.io Real-time bidirectional messaging
Message Queue Kafka Decouple message delivery, enable push notifications
Message Store Postgres (sharded by conversation_id) Persist message history
Push Service Firebase Cloud Messaging (FCM) Deliver notifications to offline users
Translation Service Google Translate API Auto-translate messages

Message Schema

Column Type Description
message_id UUID Primary key
conversation_id UUID Thread ID (booking-specific or inquiry-based)
sender_id UUID User who sent message
recipient_id UUID User who receives message
message_text TEXT Original message content
translated_text TEXT (nullable) Auto-translated version
sent_at TIMESTAMP Message send time
read_at TIMESTAMP (nullable) When recipient read message
is_automated BOOLEAN True if auto-generated (e.g., booking confirmation)

Message Delivery Flow

Step Action Component
1. Send Guest sends message via WebSocket Client β†’ WebSocket Server
2. Persist Store message in database WebSocket Server β†’ Postgres
3. Publish Publish message to Kafka topic WebSocket Server β†’ Kafka
4. Deliver (Online) If recipient online, push via WebSocket WebSocket Server β†’ Recipient Client
5. Deliver (Offline) If recipient offline, send push notification Kafka β†’ Push Service β†’ FCM
6. Translate (Optional) If recipient language differs, auto-translate Translation Worker β†’ Google Translate API

Automated Responses

Trigger Auto-Message Example
Booking Confirmed Send check-in details to guest "Your booking is confirmed! Check-in at 3pm. WiFi password: xyz123"
Inquiry Received Host's FAQ auto-reply "Thanks for your interest! We allow pets and have free parking."
Checkout Reminder Day before checkout "Reminder: checkout is 11am tomorrow. Thanks for staying!"
Interview Callout: Messaging is tied to bookings (conversation_id = booking_id) to provide context. This allows Airbnb to show booking details alongside messages and enforce policies (e.g., no off-platform payment requests).

9. Database Design

Core Tables

Table Key Columns Sharding Strategy
users user_id (PK), email, name, role (guest/host), created_at Shard by user_id (hash)
listings listing_id (PK), host_id (FK), title, description, lat, lng, price_base, max_guests Shard by listing_id (hash)
calendar listing_id (FK), date (PK), status, price, booking_id (FK) Shard by listing_id (co-locate with listings)
bookings booking_id (PK), listing_id (FK), guest_id (FK), check_in, check_out, status, total_price Shard by listing_id (join with calendar)
reviews review_id (PK), booking_id (FK), reviewer_id (FK), reviewee_id (FK), rating_overall, comment Shard by listing_id (aggregation)
messages message_id (PK), conversation_id (FK), sender_id (FK), recipient_id (FK), message_text Shard by conversation_id (hash)
payments payment_id (PK), booking_id (FK), amount, status, stripe_charge_id Shard by booking_id

Geospatial Indexing

Approach Description Use Case
PostGIS Extension Postgres with geospatial functions (ST_Distance, ST_DWithin) Backup for admin queries, analytics
Elasticsearch Geo-Point geo_point field + geo_distance query Primary search index (sub-200ms latency)
Geohash Bucketing Encode lat/lng to geohash (e.g., "9q8yy"), index as keyword Coarse filtering before precise distance calc

Sharding Strategy

Table Shard Key Rationale
listings, calendar listing_id Co-locate listing metadata + availability on same shard for fast booking queries
bookings listing_id Join with calendar during booking flow (same shard)
reviews listing_id Aggregate reviews per listing efficiently
users user_id Separate shard (user queries don't join with listings)
messages conversation_id Keep entire conversation on one shard

Replication & Consistency

Table Replication Consistency Model
bookings, calendar Synchronous replication (2 replicas) Strong consistency (no double-booking)
listings Asynchronous replication (3 replicas) Eventual consistency (read from replicas OK)
reviews Asynchronous replication Eventual consistency
messages Asynchronous replication Eventual consistency (Kafka ensures delivery)

Data Retention

Data Type Retention Policy Archive Strategy
Bookings Forever (legal, accounting) Move >3 year old bookings to cold storage (S3)
Messages 7 years (compliance) Archive to S3 after 2 years
Search Logs 90 days (analytics) Delete after 90 days
Reviews Forever (public record) No archiving
Interview Callout: Sharding by listing_id (not user_id) is key. Booking flow requires joining listings, calendar, and bookings tablesβ€”co-locating them on the same shard avoids expensive cross-shard queries. Discuss trade-offs: user queries (e.g., "show all my bookings") become scatter-gather.

10. Scalability & Performance

Search Service Scalability

Challenge Solution Impact
High Query Volume Elasticsearch cluster (50+ nodes), horizontal scaling Handle 5K QPS peak
Geo Query Latency Shard ES index by region (US-West, EU, Asia, etc.) Reduce search space, sub-100ms queries
Cache Hot Queries Redis cache for popular searches (SF, NYC, etc.) 50% cache hit rate, offload ES
Stale Availability Accept eventual consistency, re-check in booking flow Trade latency for accuracy

Booking Service Scalability

Challenge Solution Impact
Concurrent Bookings Pessimistic locks (SELECT FOR UPDATE) + idempotency keys Prevent double-booking, serializes writes
Hotspot Listings Queue booking requests per listing (FIFO) Avoid lock contention
Payment Latency Async payment processing, return 202 Accepted Improve user experience (don't block)
Expired Reservations TTL index in Postgres or cron job (every 1 min) Auto-release dates after 15 min

Image Delivery

Component Technology Optimization
Object Storage S3 (or equivalent) Store original images, multi-region replication
CDN CloudFront / Cloudflare Cache images at edge (low latency globally)
Image Resizing Lambda@Edge or Imgix Generate thumbnails on-the-fly (200x200, 800x600, etc.)
Compression WebP format for browsers that support it 50% smaller than JPEG

Database Scaling

Technique Description Use Case
Read Replicas 3-5 read replicas per shard Offload read-heavy queries (search, listing details)
Connection Pooling PgBouncer in transaction mode Reduce connection overhead
Vertical Scaling Upgrade to larger instances (more RAM, CPU) Hot shards (popular cities)
Archiving Move old bookings (>3 years) to cold storage Keep DB size manageable

Caching Strategy

Cache Layer Data Cached TTL
Redis (Application) Listing metadata, user sessions 1 hour
Redis (Search) Popular search results (SF, NYC, etc.) 5 minutes
CDN Images, static assets 1 day
Browser Cache Listing images, CSS, JS 1 week

Monitoring & Alerting

Metric Threshold Alert Action
Search Latency p99 > 500ms Scale ES cluster, investigate slow queries
Booking Error Rate > 1% Check DB locks, payment gateway
DB Connection Pool > 80% utilization Scale connection pool or replicas
Kafka Lag > 10K messages Scale consumer workers
CDN Cache Hit Rate < 90% Investigate cache misses, adjust TTLs

Disaster Recovery

Scenario Mitigation RTO / RPO
DB Shard Failure Promote read replica to master (automatic failover) RTO: 30s, RPO: 0 (sync replication)
Region Outage Multi-region active-active (route traffic to healthy region) RTO: 1 min, RPO: 5 min
ES Cluster Down Fallback to cached results or degraded mode (no search) Graceful degradation
Payment Gateway Down Queue booking requests, retry when recovered Manual intervention
Interview Callout: Airbnb's read:write ratio is 100:1 (search >> booking). The architecture reflects this: search uses eventual consistency + caching for speed, while booking requires strong consistency + locks for correctness. Discuss how to scale each path independently.