Airbnb Software Engineer
This guide features 10 challenging Software Engineer interview questions for Airbnb (Software Engineer to Staff Software Engineer levels), covering search & discovery, distributed systems, backend architecture, payment processing, and marketplace-specific challenges aligned with Airbnb’s mission of creating a world where anyone can belong anywhere.
1. Design Airbnb’s Listing Search and Discovery System
Difficulty Level: Very High
Role: Senior Software Engineer / Staff Software Engineer
Source: Code Interview, DesignGurus.io, System Design Handbook
Topic: Search & Discovery, Backend Engineering
Interview Round: System Design (45-60 min)
Engineering Domain: Distributed Systems / Search Infrastructure
Question: “Design a system allowing users to search for accommodations based on location (viewport-based search), dates, guest count, price range, and amenities, with real-time availability reflection and personalized ranking. Handle 150,000 queries/sec globally with p95 latency <200ms.”
Answer Framework
STAR Method Structure:
- Situation: Global accommodation search requires geospatial indexing, real-time availability, multi-factor ranking serving 150K QPS peak with sub-200ms latency
- Task: Design scalable search architecture balancing freshness (availability accuracy) vs performance (cache hit rates), with graceful degradation
- Action: Implement Elasticsearch with S2 geometry tiles, Redis bitmap availability cache (12-month windows), CDN for static tiles, multi-stage ranking
- Result: 80%+ cache hit rate, p95 <150ms via CDN edge caching, eventual consistency with booking-time re-verification preventing double bookings
Key Competencies Evaluated:
- Geospatial Indexing: S2 geometry, tile-based partitioning, hot shard prevention
- Caching Strategy: Multi-layer (CDN→Redis→Elasticsearch), TTL tuning, invalidation patterns
- Ranking Architecture: Multi-factor scoring, personalization integration, fallback mechanisms
- Consistency Trade-offs: Eventual consistency in search vs strong consistency at booking
Search System Architecture
GEOSPATIAL INDEXING (Elasticsearch + S2)
→ S2 Level 13: ~1km² tiles for city neighborhoods
→ Viewport converted to S2 cell IDs → multi-term query
→ Hot shard prevention: Distribute NYC/Paris across shards
AVAILABILITY CACHE (Redis Bitmap)
Key: listing_id:YYYY-MM, Value: 365-bit array
→ Bit=1: Available, Bit=0: Booked
→ Memory: 320MB for 7M listings
→ BITPOS query: O(1) availability check
MULTI-STAGE RANKING
1. Elasticsearch BM25: Text relevance + filters
2. Business Rules (Redis): Review score +20%, Superhost +15%
3. Personalization (timeout 10ms): User history, price sensitivity
→ Graceful degradation: Skip Stage 3 if timeout
CDN CACHING
→ Popular tiles: 10-min TTL, 95% hit rate
→ Long-tail: 1-min TTL or no cache
→ Invalidation: Async on new listings
QUERY FLOW (Paris, Jan 20-22, 2 guests, $100-200)
1. CDN: 5ms (cached) or miss → backend
2. Elasticsearch: 50ms geospatial + date filter
3. Ranking: 30ms composite scoring
4. Availability re-check: 20ms Redis bitmap
5. Total: 105ms p95
CONSISTENCY MODEL
Search: Eventual (10-min cache staleness acceptable)
Booking: Strong (pessimistic lock + real-time verification)Answer (Part 1 of 3): Geospatial Search & Availability Cache
Elasticsearch with S2 geometry divides earth into hierarchical tiles (level 13 ≈1km² neighborhoods) enabling viewport queries converting bounding box to S2 cell IDs searching all listings within tiles, preventing hot shards by distributing high-traffic cities across multiple shards. Redis bitmap availability cache stores 12-month calendars as 365-bit arrays (bit=1 available) consuming only 320MB for 7M listings, enabling sub-millisecond BITPOS operations checking “any blocked dates in range?” without database scans. CDN caching serves 80% searches from edge with 10-minute TTL for popular tiles (“Manhattan Jan 20-25”) achieving 95% hit rate reducing backend load 20x.
Answer (Part 2 of 3): Multi-Stage Ranking & Personalization
Three-phase ranking: (1) Elasticsearch BM25 scores text relevance combined with hard filters, (2) business rules boost quality listings (+20% for 4.8+ stars, +15% Superhost), (3) personalization queries feature server with user history and price sensitivity—critical graceful degradation skips Stage 3 on 10ms timeout preventing search outage. Composite scoring formula: final_score = 0.5×BM25 + 0.3×quality + 0.2×personalization with A/B testing determining optimal weights balancing conversion vs diversity.
Answer (Part 3 of 3): Consistency Model & Performance
Eventual consistency in search accepts 10-minute staleness (new listings delayed, price changes lag) enabling CDN caching serving 150K QPS impossible with real-time queries, compensated by strong consistency at booking re-verifying availability via pessimistic lock preventing double bookings despite stale cache—two-phase approach recognizes browsing takes 10+ minutes providing natural staleness buffer. Performance achieves p95 <150ms through layering: CDN edge 5-10ms, Redis 1-2ms, Elasticsearch 50ms, personalization 10ms timeout, with monitoring tracking cache hit rates (>80% target), p99 latency (<500ms alert), and booking conversion ensuring cached results maintain quality.
2. Prevent Double Bookings in High-Concurrency Reservation System
Difficulty Level: Very High
Role: Senior Software Engineer / Staff Software Engineer
Source: GeeksforGeeks, CodingInterview.com, InterviewQuery
Topic: Backend Engineering, Distributed Systems
Interview Round: System Design + Coding (60-90 min)
Engineering Domain: Transaction Management
Question: “Design Airbnb’s reservation system ensuring no two guests book the same listing for overlapping dates. Process 5,000 bookings/sec peak, maintain atomicity guarantees, support external calendar sync (iCal), complete booking confirmation <300ms p95.”
Answer Framework
STAR Method Structure:
- Situation: Two-sided marketplace requires atomic booking preventing race conditions when simultaneous guests attempt reservations
- Task: Design transaction system balancing throughput (5K bookings/sec) vs correctness (zero double bookings), with short hold windows
- Action: Implement pessimistic locking per listing-date range, idempotency keys, 2-minute hold TTL, outbox pattern
- Result: Zero double bookings via DB constraints + locks, 99.5% success rate, 280ms p95 latency, auto hold release
Key Competencies Evaluated:
- ACID Transactions: Isolation levels, pessimistic vs optimistic locking
- Idempotency: Deduplication strategies, idempotency key design
- Concurrency Control: Race condition prevention, hold mechanics
- Distributed Systems: Outbox pattern, eventual consistency
Reservation System Design
-- SCHEMA
CREATE TABLE reservations (
reservation_id BIGINT PRIMARY KEY AUTO_INCREMENT,
listing_id BIGINT NOT NULL,
check_in DATE NOT NULL,
check_out DATE NOT NULL, -- Exclusive
status ENUM('HOLD', 'CONFIRMED', 'CANCELLED'),
hold_expires_at TIMESTAMP,
CONSTRAINT chk_dates CHECK (check_out > check_in),
INDEX idx_listing_dates (listing_id, check_in, check_out)
);
CREATE TABLE idempotency_keys (
idempotency_key VARCHAR(64) PRIMARY KEY,
reservation_id BIGINT,
response_payload JSON,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- BOOKING FLOW
def create_reservation(listing_id, check_in, check_out, idempotency_key):
# 1. Idempotency check
if existing := get_idempotency(idempotency_key):
return existing.response
# 2. Transaction + Pessimistic lock
with db.transaction(isolation='SERIALIZABLE'):
# Lock listing row
listing = db.query("SELECT * FROM listings WHERE id=? FOR UPDATE", listing_id)
# Check overlaps: NOT (check_out <= new_start OR check_in >= new_end)
conflicts = db.query("""
SELECT id FROM reservations
WHERE listing_id=? AND status IN ('HOLD','CONFIRMED')
AND NOT (check_out <= ? OR check_in >= ?)
FOR UPDATE
""", listing_id, check_in, check_out)
if conflicts:
raise DateUnavailable
# Create HOLD (2-min TTL)
res_id = db.insert("""
INSERT INTO reservations (listing_id, check_in, check_out, status, hold_expires_at)
VALUES (?, ?, ?, 'HOLD', NOW() + INTERVAL 2 MINUTE)
""", listing_id, check_in, check_out)
# Store idempotency key
db.insert("INSERT INTO idempotency_keys VALUES (?, ?, ?)",
idempotency_key, res_id, json({'reservation_id': res_id}))
commit()
# 3. Payment capture (outside transaction)
if payment_service.authorize(amount, idempotency_key):
db.execute("UPDATE reservations SET status='CONFIRMED' WHERE id=?", res_id)
# Outbox pattern for downstream events
db.insert("INSERT INTO outbox VALUES ('booking.confirmed', ?)", res_id)
else:
release_hold(res_id)
# TTL cleanup (runs every 30s)
def cleanup_expired():
db.execute("UPDATE reservations SET status='CANCELLED' WHERE status='HOLD' AND hold_expires_at < NOW()")
OVERLAP LOGIC
Intervals [A_start, A_end) and [B_start, B_end) overlap if:
NOT (A_end <= B_start OR A_start >= B_end)
Example: Existing Jan 5-10, New Jan 8-12
→ NOT (10 <= 8 OR 5 >= 12) → TRUE (conflict!)Answer
Atomic booking prevents double bookings via SERIALIZABLE transaction with pessimistic row locking (SELECT ... FOR UPDATE) ensuring concurrent attempts execute sequentially—overlap detection checks all HOLD/CONFIRMED reservations using interval arithmetic (conflict if NOT (check_out<=new_start OR check_in>=new_end)). 2-minute hold window creates temporary HOLD during payment authorization avoiding inventory lockup if guest abandons, with automated TTL cleanup every 30 seconds freeing expired holds—balances conversion (longer holds) vs lost revenue (shorter holds). Idempotency keys prevent duplicates from retries by storing client UUID: first request processes normally caching response, duplicates return cached response without mutation. Outbox pattern achieves eventual consistency for downstream (search reindex, notifications) by inserting events in same transaction as reservation, separate relay publishes to Kafka with at-least-once guarantees decoupling hot path (<300ms booking) from fan-out (1-min lag tolerable).
3. Calendar Overlap Detection (Coding Challenge)
Difficulty Level: High
Role: Software Engineer / Senior Software Engineer
Source: LeetCode (My Calendar I & II), CodingInterview.com
Topic: Algorithms, Data Structures
Interview Round: Technical Phone Screen (45-60 min)
Engineering Domain: Interval Scheduling
Question: “Implement My Calendar I: Add events preventing double bookings. My Calendar II: Allow double bookings but prevent triple bookings. Return true if event can be added, false otherwise.”
Answer Framework
STAR Method Structure:
- Situation: Calendar booking requires efficient overlap detection preventing conflicts
- Task: Implement O(log n) insertion for Calendar I, O(n) for Calendar II tracking double-booked regions
- Action: Use SortedList with binary search (I), maintain double-booking tracker (II)
- Result: O(log n) Calendar I via sorted structure, O(n) Calendar II checking all overlaps
Key Competencies Evaluated:
- Interval Arithmetic: Overlap conditions, intersection logic
- Data Structure Selection: SortedList vs TreeMap trade-offs
- Complexity Analysis: Optimizing insertion/query balance
Implementation
from sortedcontainers import SortedList
class MyCalendarOne:
def __init__(self):
self.bookings = SortedList()
def book(self, start: int, end: int) -> bool:
idx = self.bookings.bisect_left((start, end))
# Check previous interval
if idx > 0 and self.bookings[idx-1][1] > start:
return False
# Check next interval
if idx < len(self.bookings) and self.bookings[idx][0] < end:
return False
self.bookings.add((start, end))
return True
class MyCalendarTwo:
def __init__(self):
self.bookings = []
self.double_bookings = []
def book(self, start: int, end: int) -> bool:
# Check against double bookings (would create triple)
for d_start, d_end in self.double_bookings:
if max(start, d_start) < min(end, d_end):
return False # Triple booking
# Add overlaps to double bookings
for b_start, b_end in self.bookings:
overlap_start = max(start, b_start)
overlap_end = min(end, b_end)
if overlap_start < overlap_end:
self.double_bookings.append((overlap_start, overlap_end))
self.bookings.append((start, end))
return True
# Overlap formula: [start1,end1) and [start2,end2) overlap if max(start1,start2) < min(end1,end2)
# Complexity: Calendar I O(log n), Calendar II O(n)Answer
Calendar I uses SortedList enabling O(log n) binary search for insertion index, checking only adjacent intervals (previous overlaps if prev_end>start, next overlaps if next_start<end)—sorted structure eliminates O(n) full scan. Calendar II maintains bookings list (all events) and double_bookings list (overlap regions), with new event first checking all double_bookings (any overlap creates forbidden triple booking), then computing intersections with existing bookings adding new overlaps to double_bookings—accepts O(n) as correctness requires tracking all double-booked regions. Overlap detection: intervals [start1,end1) and [start2,end2) overlap if max(start1,start2) < min(end1,end2), with intersection [max(start1,start2), min(end1,end2))—half-open semantics [start,end) means [5,10) and [10,15) don’t overlap sharing only boundary.
4. Design Dynamic Pricing and Price Optimization Service
Difficulty Level: Very High
Role: Senior Software Engineer / Staff Software Engineer
Source: CodingInterview.com, Educative.io
Topic: Machine Learning Infrastructure, Backend
Interview Round: System Design (45-60 min)
Engineering Domain: Data Platform / ML Serving
Question: “Design dynamic pricing service suggesting optimal nightly prices based on demand, seasonality, lead time, competitor pricing, historical occupancy, and host constraints. Update nightly, serve at <20ms latency, handle millions of listings, provide feedback loops.”
Answer Framework
STAR Method Structure:
- Situation: Marketplace pricing requires ML optimization processing millions of signals nightly
- Task: Design batch pipeline + online serving <20ms, feedback loop incorporating outcomes
- Action: Spark feature engineering, XGBoost prediction, Redis caching, counterfactual analysis
- Result: 7M listings daily refresh, <15ms p95 latency, +18% revenue, monthly retraining
Key Competencies Evaluated:
- Batch/Stream Architecture: Offline training vs online serving
- Feature Engineering: Extracting predictive signals
- Online Serving: Low-latency caching strategies
- Feedback Loops: Closed-loop learning
Dynamic Pricing Architecture
# OFFLINE BATCH (Nightly Spark)
class PricingModel:
def extract_features(listing_id, date):
return {
'booking_velocity_7d': count_bookings(7), # Short-term demand
'market_occupancy': get_neighborhood_occupancy(date),
'is_weekend': date.weekday() >= 5,
'lead_time': (date - now()).days,
'competitor_median_price': get_similar_listings_price(date),
'review_score': listing.reviews,
'superhost': listing.is_superhost
}
def predict_price(features):
base = xgb_model.predict(features) # XGBoost regression
# Apply host constraints
min_price = host_constraints.get('min',0)
max_price = host_constraints.get('max', inf)
max_change = prev_price * 0.20 # 20% max daily change
return clamp(base, min_price, max_price, prev_price ± max_change)
# ONLINE SERVING (Redis <5ms)
class PricingCache:
def get_suggestion(listing_id, date):
key = f"listing:{listing_id}:date:{date}"
return redis.get(key) # Pre-computed, 48h TTL
def batch_populate(suggestions):
pipeline = redis.pipeline()
for (listing, date, price) in suggestions:
pipeline.setex(f"listing:{listing}:date:{date}", 172800, price)
pipeline.execute() # Batch write for 2.5B keys
# FEEDBACK LOOP (Monthly)
def analyze_outcomes(month):
for booking in bookings[month]:
suggested = suggestions.get((listing, date))
actual = booking.price
if actual > suggested:
# Underpredicted demand → adjust elasticity
outcomes.append({'listing': listing, 'elasticity': +25%})
elif not booked:
# Overpredicted → lower price
outcomes.append({'listing': listing, 'adjustment': -10%})
model.retrain(training_data + outcomes) # Monthly retraining
# ARCHITECTURE
# Offline: Spark extracts features → XGBoost predicts → Redis batch write (3AM)
# Online: Search queries Redis → <5ms lookup → Display suggestion
# Feedback: Booking outcomes → Counterfactual analysis → Monthly retrain
# METRICS
# Serving: <15ms p95, Coverage: 98%
# Business: +18% revenue, +2% conversion (10%→12%)
# Model: RMSE $25, Override rate 30% (acceptable)Answer
Offline batch pipeline (Spark nightly 3AM) extracts features: booking velocity (7/30/90-day windows), market occupancy (neighborhood aggregation), seasonality (weekend/holidays), lead-time, competitor prices, listing quality—feeds XGBoost predicting optimal price maximizing revenue=price×P(booked), with host constraints (min/max price, 20% max daily change) applied post-prediction. Online serving via Redis keyed by listing:id:date:YYYY-MM-DD storing pre-computed prices for 365 days×7M listings (2.5B entries, ~50GB), achieving <5ms p95 lookup with 48h TTL, batch population using pipelined writes completing 7M listings in 45 minutes. Feedback loop ingests monthly booking outcomes comparing suggested vs actual prices: booked-at-$150-when-suggested-$120 indicates underpredicted demand (+25% elasticity adjustment), unbooked-at-suggested-$180 indicates overprediction requiring downward correction—retraining incorporates 1.5M outcomes/month with performance tracked via conversion rate (+20% lift to 12%), revenue per listing (+18%), and RMSE ($25 acceptable for $100-500 range).
5. Host-Guest Messaging System with Real-Time Updates
Difficulty Level: High
Role: Senior Software Engineer / Staff Software Engineer
Source: CodingInterview.com, InterviewQuery
Topic: Distributed Systems, Messaging
Interview Round: System Design (60 min)
Engineering Domain: Real-Time Infrastructure
Question: “Design reliable messaging system for host-guest communication supporting real-time delivery, read receipts, multi-year history, content moderation (toxicity detection, PII redaction), spam prevention, notification delivery (push/email/SMS). Handle 200,000 messages/sec.”
Answer Framework
STAR Method Structure:
- Situation: Real-time messaging requires ordered delivery, moderation, receipts, tiered storage for 200K msg/sec
- Task: Design append-only log with WebSocket fanout, two-phase moderation (inline+async), tiered retention
- Action: Kafka partitioned by thread_id, WebSocket for push, inline keyword filters, async ML toxicity, hot/warm/cold storage
- Result: Sequential delivery within threads, <5ms inline moderation, 95% queries hit hot storage (30 days), multi-year compliance
Key Competencies Evaluated:
- WebSocket Management: Persistent connections, fanout patterns
- Pub-Sub Architecture: Kafka partitioning, at-least-once delivery
- Moderation Pipeline: Inline vs async trade-offs
- Tiered Storage: Hot/warm/cold cost optimization
Messaging System Architecture
# WRITE PATH
def send_message(thread_id, sender_id, content):
# 1. Inline moderation (<5ms)
if contains_blacklist_url(content) or has_profanity(content):
raise ModerationRejected
# PII redaction
content = redact_pii(content) # Remove credit cards, SSNs
# 2. Write to Kafka (partitioned by thread_id for ordering)
message_id = kafka.produce(
topic='messages',
key=thread_id, # Ensures same partition → ordering
value={'thread_id': thread_id, 'sender': sender_id, 'content': content, 'timestamp': now()}
)
# 3. Async ML toxicity check (post-delivery)
toxicity_queue.enqueue({'message_id': message_id, 'content': content})
return {'message_id': message_id, 'status': 'delivered'}
# FANOUT (WebSocket Server subscribes to Kafka)
class WebSocketServer:
def on_kafka_message(msg):
thread_id = msg['thread_id']
recipients = get_thread_participants(thread_id)
for recipient in recipients:
if recipient.ws_connected:
recipient.ws_send(msg) # Real-time push
else:
notification_service.notify(recipient, msg) # Email/SMS fallback
# READ RECEIPTS
def send_read_receipt(thread_id, message_id, user_id):
receipt_stream.publish({
'thread_id': thread_id,
'user_id': user_id,
'last_read_message_id': message_id,
'timestamp': now()
})
# Fanout to sender's WebSocket showing "read" indicator
sender_ws.send({'type': 'read_receipt', 'message_id': message_id})
# TIERED STORAGE
class MessageStorage:
def get_messages(thread_id, limit=50):
# Hot: <30 days (PostgreSQL) → 100ms
if recent := hot_db.query("SELECT * FROM messages WHERE thread_id=? AND created_at > NOW() - 30 LIMIT ?", thread_id, limit):
return recent
# Warm: 30-365 days (Parquet on S3) → 500ms
if warm := s3_parquet.query(f"s3://messages/year=2024/month={month}/thread={thread_id}.parquet"):
return warm
# Cold: >1 year (Glacier, async retrieval) → 30 seconds
return glacier.async_retrieve(thread_id)
# ARCHITECTURE
# Write: Client → WebSocket → Inline moderation → Kafka → ACK
# Fanout: Kafka Consumer → WebSocket push (connected) / Notification (offline)
# Read receipts: Separate event stream → ACK tracking
# Moderation: Inline filters (<5ms) + Async ML (post-delivery flagging)
# Storage: Hot (30d PostgreSQL) / Warm (1y Parquet S3) / Cold (Glacier)
# METRICS
# Throughput: 200K msg/sec, Latency: <50ms delivery
# Moderation: <5ms inline, 200ms async ML
# Storage: 95% queries hit hot tierAnswer
Append-only log partitioned by thread_id via Kafka ensures total ordering within conversations with WebSocket connections maintaining persistent channels for real-time push eliminating polling—write path validates auth, applies inline keyword filters (<5ms budget) rejecting blacklisted URLs/profanity, redacts PII (credit cards, SSNs) inline before Kafka write, then async ML toxicity model (BERT classifier) flags suspicious messages post-delivery for human review accepting brief window vs blocking real-time flow. Fanout via WebSocket server subscribing to Kafka consumes messages pushing to connected users, with offline users receiving notifications (push/email/SMS) via polling service—read receipts track delivery/read status via separate event stream where recipient ACKs propagate back to sender’s WebSocket displaying “delivered/read” indicators, idempotency keys preventing duplicate ACK processing from network retries. Tiered storage optimizes cost vs latency: hot (<30 days) in PostgreSQL serving 95% queries at 100ms, warm (30-365 days) in Parquet on S3 at 500ms, cold (>1 year) in Glacier requiring async retrieval (30 seconds) for compliance-required multi-year retention balancing frequent recent access against infrequent historical queries.
6. Distributed Payment Processing with Idempotency
Difficulty Level: Very High
Role: Senior Software Engineer / Staff Software Engineer
Source: GeeksforGeeks, CodingInterview.com
Topic: Payment Systems, Distributed Transactions
Interview Round: System Design (60 min)
Engineering Domain: Financial Systems
Question: “Design Airbnb payment processing handling payment splitting (guest, host, fees), pre-authorization during hold, capture at confirmation, multiple currencies, VAT/tax compliance, preventing double-charging, supporting refund/chargeback workflows.”
Answer Framework
STAR Method Structure:
- Situation: Payment processing requires three-phase flow (authorize→hold→capture) with splitting, idempotency, tax compliance
- Task: Design transaction system coordinating booking service + payment processors, preventing double-charging, handling disputes
- Action: Client-generated idempotency keys, saga pattern for compensating transactions, audit trail for compliance
- Result: End-to-end idempotency, <0.3% chargeback rate, fraud detection window before host payout, regulatory compliance
Key Competencies Evaluated:
- Idempotent Operations: UUID deduplication across retries
- Saga Patterns: Compensating transactions for failures
- PCI-DSS Compliance: Secure payment handling
- Compensating Transactions: Reversal logic for failures
Payment System Design
# THREE-PHASE FLOW
def process_booking_payment(booking_id, payment_method, idempotency_key):
# 1. AUTHORIZE (7-day hold, no settlement)
auth = stripe.authorize(
amount=calculate_total(booking_id),
payment_method=payment_method,
idempotency_key=idempotency_key # Stripe deduplication
)
if not auth.success:
return {'error': 'authorization_failed'}
# 2. HOLD (2-min checkout window)
reservation_id = create_reservation_hold(booking_id, auth_id=auth.id, ttl=120)
# 3. CAPTURE (on checkout completion)
if checkout_completed:
capture = stripe.capture(auth.id, idempotency_key=f"{idempotency_key}_capture")
if capture.success:
confirm_reservation(reservation_id)
# Payment splitting (post-capture)
schedule_host_payout(
amount=capture.amount - service_fee - taxes,
host_id=booking.host_id,
payout_date=check_in_date + 1 # Fraud window
)
# Tax withholding
remit_taxes(
amount=calculate_vat(booking),
jurisdiction=get_tax_jurisdiction(booking.location)
)
else:
# COMPENSATING TRANSACTION
stripe.reverse_authorization(auth.id)
release_reservation_hold(reservation_id)
return {'status': 'confirmed', 'reservation_id': reservation_id}
# IDEMPOTENCY TABLE
CREATE TABLE payment_transactions (
idempotency_key VARCHAR(64) PRIMARY KEY,
booking_id BIGINT,
auth_id VARCHAR(255),
capture_id VARCHAR(255),
status ENUM('AUTHORIZED','CAPTURED','REVERSED'),
amount DECIMAL(10,2),
created_at TIMESTAMP
);
# CHARGEBACK HANDLING
def handle_chargeback_webhook(chargeback_event):
# Stripe webhook: guest disputed charge
booking_id = chargeback_event['metadata']['booking_id']
# Freeze funds pending investigation
freeze_host_payout(booking_id)
# Auto-gather evidence
evidence = {
'booking_confirmation': get_booking_email(booking_id),
'messages': get_host_guest_messages(booking_id),
'check_in_timestamp': get_check_in_log(booking_id),
'photos': get_listing_photos(booking_id)
}
stripe.submit_chargeback_evidence(chargeback_event.id, evidence)
# Monitor chargeback rate (target <0.3%)
if get_chargeback_rate() > 0.003:
alert_fraud_team()
# SAGA PATTERN EXAMPLE
try:
auth = authorize_payment()
hold = create_reservation()
capture = capture_payment()
schedule_payout()
except PaymentError:
# Compensating: Reverse successfully completed steps
if capture: refund_payment()
if hold: release_hold()
if auth: reverse_authorization()
# COMPLIANCE
- Immutable ledger: All transactions logged for audit trail
- Tax calculation: Jurisdiction lookup (EU VAT, US state tax)
- Payment splitting: Guest → Airbnb → Host (check-in +1 day for fraud detection)
- PCI-DSS: Never store card details, delegate to Stripe/AdyenAnswer
Three-phase flow (authorize→hold→capture) creates 7-day authorization binding guest funds without settlement, 2-minute hold window during checkout completion, then capture converts to settled transaction—idempotency enforced via client-generated UUID stored in payment_transactions table preventing duplicate processing when network failures cause retries, with idempotency_key passed to Stripe ensuring their systems deduplicate creating end-to-end protection. Payment splitting occurs post-capture: Airbnb receives full guest payment, schedules host payout (amount minus service fee minus taxes) for check-in+1 day providing fraud detection window before irreversible transfer, with tax withholding calculated per jurisdiction (EU VAT, US state sales tax) requiring geographic lookup and regulatory compliance maintaining audit trail linking payment→payout→tax. Compensating transactions via saga pattern handle failures: if authorization succeeds but booking fails, issue reverse-authorization releasing funds; if capture succeeds but notification fails, retry idempotently accepting temporary inconsistency—demonstrates distributed challenges where two-phase commit infeasible across third-party providers requiring application-level compensation. Chargeback workflow: guest dispute via issuer→Stripe webhook→freeze funds→auto-gather evidence (confirmation, messages, check-in log)→submit to issuer→resolution updates reservation, with monitoring tracking chargeback rate (target <0.3%) as excessive disputes trigger processor review potentially suspending payments making fraud prevention critical business continuity.
7. Fraud Detection System for Real-Time Booking Decisions
Difficulty Level: High
Role: Senior Software Engineer / Staff Software Engineer
Source: CodingInterview.com, Educative.io
Topic: ML Ops, Security
Interview Round: System Design (45-60 min)
Engineering Domain: Trust & Safety
Question: “Design fraud detection identifying fraudulent bookings, fake listings, account takeovers, payment fraud in real-time. Score high-risk transactions within 50ms, support rules + ML, allow human review for borderline cases, provide feedback loops from chargebacks.”
Answer Framework
STAR Method Structure:
- Situation: Real-time fraud scoring must balance latency (<50ms) vs accuracy, with human review for edge cases
- Task: Design lightweight rules engine + async ML model, feature service, H ITL review queue, feedback loop
- Action: Rules score 0-100 (<10ms), ML processes richer features async (200ms), borderline→human review, monthly retraining
- Result: <50ms inline scoring, 40-80 risk score→15-min human SLA, <0.3% chargeback rate, <2% false positives
Key Competencies Evaluated:
- Feature Engineering: Fraud signal extraction
- Real-Time Scoring: Latency constraints vs model richness
- Precision/Recall Trade-offs: Balancing false positives vs negatives
- Feedback Loops: Continuous learning from outcomes
Fraud Detection Architecture
# REAL-TIME RULES ENGINE (<10ms)
def score_booking(user_id, listing_id, payment_method, context):
risk_score = 0
# Velocity checks
if count_bookings_last_hour(user_id) > 5:
risk_score += 30 # Suspicious rapid booking
# IP reputation
if is_vpn_or_proxy(context.ip_address):
risk_score += 15
# Device fingerprinting
if multiple_accounts_same_device(context.device_hash):
risk_score += 25
# Payment method
if new_card_from_high_risk_country(payment_method):
risk_score += 20
# Decision thresholds
if risk_score > 80:
return 'BLOCK'
elif risk_score > 40:
return 'HUMAN_REVIEW'
else:
return 'APPROVE'
# ASYNC ML MODEL (200ms, post-booking)
class FraudMLModel:
def predict(user_id, listing_id):
features = {
# User behavior graph
'typical_price_range': get_user_booking_history(user_id).price_stats,
'destination_clusters': analyze_past_destinations(user_id),
'first_luxury_booking': is_anomaly(listing_id, user_history),
# Listing attributes
'new_listing_with_pro_photos': (
listing.age_days < 30 and
listing.photo_quality_score > 8 and
listing.reviews_count == 0
),
# Network features
'circular_booking_pattern': detect_fraud_ring(user_id),
# Temporal
'overseas_booking_during_sleep': (
booking_time in user_sleep_hours(user_id) and
listing.location != user.typical_location
)
}
return xgb_model.predict_proba(features)['fraud']
# FEATURE SERVICE (Redis cached, hourly refresh)
class FraudFeatureService:
def get_user_profile(user_id):
# Cached features to avoid heavy computation on hot path
return redis.hgetall(f"fraud_features:user:{user_id}") # <1ms
# HUMAN-IN-THE-LOOP REVIEW QUEUE
def route_to_review(booking_id, risk_score):
review_queue.enqueue({
'booking_id': booking_id,
'risk_score': risk_score,
'signals': {
'account_age': user.created_days_ago,
'previous_bookings': count_successful_bookings(user_id),
'message_sentiment': analyze_messages(booking_id),
'similarity_to_known_fraud': cosine_similarity(booking, fraud_db)
},
'sla': '15_minutes'
})
# Investigator dashboard
# → Manual decision: APPROVE / REJECT
# → Feeds back to training pipeline as ground truth label
# FEEDBACK LOOP (Monthly Retraining)
def retrain_fraud_model():
# Collect outcomes
false_positives = get_user_appeals(month) # Legit bookings blocked
false_negatives = get_chargebacks(month) # Fraud allowed through
true_positives = get_caught_fraud(month)
# Recalibrate decision thresholds
optimize_threshold(
precision_target=0.98, # Minimize false positives
recall_target=0.95 # Minimize false negatives
)
# Retrain model
training_data = historical_data + new_labels
model.fit(training_data)
# Monitor model drift
if prediction_distribution_shift() > threshold:
alert('Fraud tactics evolved, model drift detected')
# METRICS
# Inline scoring: <10ms (rules), <50ms total
# Async ML: 200ms (non-blocking)
# Human review: 15-min SLA for risk_score 40-80
# Business: <0.3% chargeback rate, <2% false positive rate
# Model: F1 score 0.96, monthly retrainingAnswer
Lightweight rules engine (<10ms) checks velocity (>5 bookings/hour suspicious), IP reputation (VPN/proxy flagged), device fingerprinting (multiple accounts same browser hash), payment method (new card from high-risk country), accumulating risk score 0-100 where >80 auto-blocks, 40-80 queues human review, <40 auto-approves—parallel async ML model processes richer features (user behavior graphs, listing anomalies, network fraud rings, temporal patterns) returning 200ms prediction consumed post-booking for improvement not blocking checkout. Feature service aggregates cached signals in Redis (refreshed hourly): user booking patterns (price range, destinations, lead time detecting anomalies like first luxury after 20 budget trips), listing attributes (new+professional photos+zero reviews=scam), network features (circular booking patterns), temporal (overseas booking during sleep hours)—balances freshness vs compute as full recalculation prohibitively expensive for 100M profiles. Human-in-the-loop routes borderline (40-80 risk) to investigators viewing dashboards showing account age, booking history, message sentiment, similarity to known fraud taking accept/reject within 15-min SLA feeding ground truth labels to training—critical feedback loop where false positives (legit bookings blocked) and false negatives (fraud discovered via chargeback) update model monthly retraining recalibrating thresholds optimizing F1 balancing precision (minimize annoyed customers) vs recall (minimize losses). Monitoring tracks chargeback rate (<0.3% target), false positive rate via appeals (<2%), model drift via prediction distribution shifts indicating evolved fraud tactics requiring retraining.
8. Full-Stack Listing Search with React Frontend
Difficulty Level: High
Role: Senior Frontend Engineer / Full-Stack Engineer
Source: GreatFrontEnd, CodingInterview.com
Topic: Frontend Engineering, Full-Stack
Interview Round: System Design + Implementation (90-120 min)
Engineering Domain: UI/UX Architecture
Question: “Design and implement frontend for Airbnb search results page: (1) responsive map with listing pins and price overlays, (2) filterable list (price, bedrooms, ratings), (3) pagination/infinite scroll, (4) real-time availability updates, (5) component library scaling across verticals. Use React, optimize for mobile.”
Answer Framework
STAR Method Structure:
- Situation: Search UI requires map integration, filtering, virtualization, real-time updates, mobile optimization
- Task: Design component architecture with state management, WebSocket updates, performance optimization
- Action: React Query for API caching, react-window virtualization, Mapbox integration, debounced filters, code splitting
- Result: <3s First Contentful Paint, 50 DOM nodes for 500 results (10x memory reduction), >90 Lighthouse score mobile
Key Competencies Evaluated:
- React Architecture: Component decomposition, reusability
- State Management: React Query caching, filter coordination
- Performance Optimization: Virtualization, code splitting, lazy loading
- Responsive Design: Mobile-first, progressive enhancement
React Frontend Architecture
// COMPONENT STRUCTURE
import { useQuery } from 'react-query';
import { FixedSizeList } from 'react-window';
function SearchResultsPage() {
const [filters, setFilters] = useState({
priceRange: [0, 500],
bedrooms: null,
ratings: null
});
// Debounced API calls (300ms)
const debouncedFilters = useDebounce(filters, 300);
// React Query caching (keyed by filters)
const { data, isLoading } = useQuery(
['listings', debouncedFilters],
() => fetchListings(debouncedFilters),
{ staleTime: 60000 } // 1-min cache
);
return (
<div className="search-layout">
<SearchFilters filters={filters} onChange={setFilters} />
<ListingGrid listings={data?.listings} />
<MapView listings={data?.listings} />
</div>
);
}
// VIRTUALIZED LIST (react-window)
function ListingGrid({ listings }) {
return (
<FixedSizeList
height={800}
itemCount={listings.length}
itemSize={200}
width="100%"
>
{({ index, style }) => (
<ListingCard listing={listings[index]} style={style} />
)}
</FixedSizeList>
);
}
// LAZY-LOADED IMAGES
function ListingCard({ listing }) {
const imgRef = useRef();
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true);
observer.disconnect();
}
});
observer.observe(imgRef.current);
}, []);
return (
<div className="listing-card">
<img
ref={imgRef}
src={isVisible ? listing.imageUrl : placeholder}
alt={listing.title}
loading="lazy"
/>
<h3>{listing.title}</h3>
<p>${listing.price}/night ⭐{listing.rating}</p>
</div>
);
}
// REAL-TIME AVAILABILITY (WebSocket)
function useRealtimeAvailability() {
const queryClient = useQueryClient();
useEffect(() => {
const ws = new WebSocket('wss://api.airbnb.com/listing_updates');
ws.onmessage = (event) => {
const { listing_id, dates_booked } = JSON.parse(event.data);
// Invalidate cache + show toast
queryClient.invalidateQueries(['listings']);
toast.info(`Listing${listing_id} just booked!`);
};
return () => ws.close();
}, []);
}
// MAP INTEGRATION (Mapbox)
function MapView({ listings }) {
const mapRef = useRef();
useEffect(() => {
const map = new mapboxgl.Map({
container: mapRef.current,
style: 'mapbox://styles/mapbox/streets-v11',
center: [-73.9, 40.7], // NYC
zoom: 12
});
// Add listing pins
listings.forEach(listing => {
new mapboxgl.Marker()
.setLngLat([listing.lng, listing.lat])
.setPopup(new mapboxgl.Popup().setText(`$${listing.price}`))
.addTo(map);
});
}, [listings]);
return<div ref={mapRef} style={{width: '100%', height: '600px'}} />;
}
// PAGINATION (Cursor-based)
function usePagination(filters) {
const [nextCursor, setNextCursor] = useState(null);
const { data, fetchNextPage } = useInfiniteQuery(
['listings', filters],
({ pageParam = null }) =>
fetchListings({...filters, cursor: pageParam}),
{
getNextPageParam: (lastPage) => lastPage.nextCursor
}
);
return { listings: data?.pages.flatMap(p => p.listings), fetchNextPage };
}
// PERFORMANCE OPTIMIZATION
// 1. Code splitting: Lazy load Map component
const LazyMapView = React.lazy(() => import('./MapView'));
// 2. Debounced filters (300ms)
// 3. React Query caching (1-min stale time)
// 4. Image lazy loading (Intersection Observer)
// 5. Virtualization (react-window: 50 DOM nodes for 500 results)
// RESPONSIVE DESIGN
@media (max-width: 768px) {
.search-layout {
flex-direction: column; /* Stack map below list */
}
.map-view { height: 300px; } /* Shorter on mobile */
}
// METRICS
// FCP: <3s on 3G, Lighthouse: >90 mobile
// Memory: 50 DOM nodes (10x reduction via virtualization)
// Bundle size: 200KB (code splitting)Answer
Component architecture decomposes page into <SearchFilters> managing filter state with debounced onChange (300ms) preventing excessive API calls, <ListingGrid> using react-window virtualization rendering only visible rows (50 DOM nodes for 500 results reducing memory 10x), <MapView> integrating Mapbox showing geo-clustered pins with price overlays, <ListingCard> lazy-loading images via Intersection Observer—React Query caches API responses keyed by filter hash preventing redundant fetches on map/list toggle. Real-time availability implements WebSocket subscribing to listing_updates receiving {listing_id, dates_booked} events when concurrent booking occurs, invalidating local cache removing newly-unavailable listings displaying “just booked” toast—fallback to 30-second polling when WebSocket blocked ensuring degraded but functional experience. Pagination uses cursor-based approach (next_token=encoded_position) avoiding count offset issues when results change between fetches, with infinite scroll on mobile (thumb scrolling) and pagination on desktop (deep exploration, SEO-friendly URLs) as users exhibit different browsing patterns. Performance optimization achieves <3s First Contentful Paint via code splitting (Map bundle loaded async after initial render), image optimization (WebP with JPEG fallback, srcset for responsive sizes), CSS-in-JS memoization, debounced filter batching, with Lighthouse >90 mobile simulating 3G throttling ensuring global accessibility.
9. Calendar Synchronization with External iCal Feeds
Difficulty Level: High
Role: Senior Software Engineer
Source: CodingInterview.com
Topic: Data Synchronization, Backend
Interview Round: System Design (45-60 min)
Engineering Domain: Integration Systems
Question: “Design system synchronizing external calendar feeds (iCal URLs, Google Calendar, Outlook) with Airbnb calendars. External blocks must immediately remove availability. Handle polling of flaky feeds, conflict resolution, incremental delta syncing, expose sync status to host UI. SLA: sync within 5 minutes.”
Answer Framework
STAR Method Structure:
- Situation: External calendar integration requires polling unreliable feeds, delta computation, conflict handling
- Task: Design scheduler polling 5-min intervals, ETag caching, fail-safe conflict resolution, state machine tracking
- Action: Distributed cron with shard assignment, HTTP conditional requests, RRULE→date expansion, exponential backoff
- Result: 5-min sync SLA for 95% feeds, fail-safe conflict handling, state machine (SYNCING/IN_SYNC/STALE/FAILED)
Key Competencies Evaluated:
- Polling vs Webhooks: Trade-offs, fallback strategies
- Delta Computation: Minimizing redundant updates
- Conflict Resolution: Fail-safe prioritization
- Error Handling: Exponential backoff, quarantine
Calendar Sync Architecture
# POLLING SCHEDULER (Distributed Cron)
class CalendarSyncScheduler:
def schedule_sync(host_id, feed_url):
# Shard assignment: hash(feed_url) % num_workers
shard = hash(feed_url) % WORKER_COUNT
# 5-minute interval per feed
cron.schedule(
interval=300,
shard=shard,
task=sync_feed,
args=(host_id, feed_url)
)
# SYNC FLOW
def sync_feed(host_id, feed_url):
# 1. HTTP conditional request (ETag/If-Modified-Since)
response = requests.get(
feed_url,
headers={
'If-Modified-Since': last_sync_timestamp,
'If-None-Match': stored_etag
},
timeout=5
)
if response.status_code == 304:
# Feed unchanged, skip processing
update_sync_status(host_id, 'IN_SYNC')
return
# 2. Parse iCal events
ical = Calendar.from_ical(response.content)
external_events = []
for component in ical.walk('VEVENT'):
event = {
'uid': component.get('UID'),
'start': component.get('DTSTART').dt,
'end': component.get('DTEND').dt,
'rrule': component.get('RRULE') # Recurrence rule
}
# Expand recurrence rules to explicit dates
if event['rrule']:
event['dates'] = expand_rrule(event['rrule'], max_years=2)
external_events.append(event)
# 3. Delta computation
local_events = get_local_calendar(host_id)
adds = [e for e in external_events if e['uid'] not in local_events_map]
removes = [e for e in local_events if e['uid'] not in external_events_map]
modifications = [e for e in external_events
if e['uid'] in local_events_map and e != local_events_map[e['uid']]]
# 4. Apply changes (incremental, not full rewrite)
for event in adds:
block_dates(host_id, event['dates'])
for event in removes:
unblock_dates(host_id, event['dates'])
for event in modifications:
update_blocked_dates(host_id, old=local_events_map[event['uid']], new=event)
# 5. Update sync status
update_sync_status(host_id, 'IN_SYNC', timestamp=now(), etag=response.headers['ETag'])
# CONFLICT RESOLUTION (Fail-Safe)
def handle_conflict(external_blocked, airbnb_booking_pending):
"""
If external calendar shows date blocked but Airbnb has pending guest booking:
→ ALLOW booking completion (guest already initiated)
→ PREVENT new bookings for that date
→ WARN host: "External calendar may have conflict"
Rationale: Temporary iCal fetch failures shouldn't cancel legitimate bookings
"""
if airbnb_booking_pending:
complete_pending_booking()
prevent_new_bookings(date)
notify_host("External calendar conflict detected")
else:
block_date_immediately()
# ERROR HANDLING (Exponential Backoff)
def handle_sync_failure(host_id, feed_url, error):
failure_count = get_failure_count(host_id)
if failure_count < 3:
# Retry with exponential backoff
next_attempt = {
1: 10 * 60, # 10 min
2: 30 * 60, # 30 min
3: 60 * 60 # 1 hour
}[failure_count]
schedule_retry(host_id, feed_url, delay=next_attempt)
update_sync_status(host_id, 'STALE')
elif failure_count >= 3:
# Quarantine (stop polling)
update_sync_status(host_id, 'FAILED')
notify_host("Calendar sync failing. Click 'Retry Now' or update manually.")
# Preserve last successfully synced state
# STATE MACHINE
# SYNCING → IN_SYNC (success, timestamp <5min)
# SYNCING → STALE (success but timestamp >1 hour)
# SYNCING → FAILED (consecutive errors ≥3)
# FAILED → SYNCING (manual "Retry Now" button)
# WEBHOOK SUPPORT (where available)
def register_webhook(google_calendar_id):
"""
Google Calendar supports push notifications via Watch API
→ Sub-minute latency vs 5-min polling
→ Still maintain polling as fallback (not all providers support)
"""
google.calendar().events().watch(calendarId=calendar_id, body={
'id': uuid4(),
'type': 'web_hook',
'address': 'https://airbnb.com/webhooks/calendar'
})
# METRICS
# Sync SLA: 95% within 5 minutes
# Failure rate: <5% (flaky feeds)
# Quarantine rate: <1% (permanently broken)Answer
Polling architecture schedules 5-minute fetches per feed URL via distributed cron with shard assignment (hash(url) % workers) ensuring single worker per feed preventing duplicates, using HTTP conditional requests (ETag/If-Modified-Since) enabling 304 Not Modified when unchanged avoiding parse overhead—webhook ingestion for Google Calendar provides sub-minute latency but polling remains fallback as most iCal exports lack webhook support. Delta computation compares fetched events against local state identifying adds/removes/modifications via event UID matching, translating iCal recurrence rules (RRULE) to explicit date ranges, with incremental updates (only changed dates) minimizing database writes vs full 365-day rewrite every 5 minutes. Conflict resolution prioritizes external blocks fail-safe: if iCal blocked but Airbnb booking pending, allow completion preventing new bookings for that date until manual resolution displaying “External calendar conflict” warning—alternative auto-cancelling rejected as too aggressive risking legitimate bookings cancelled from temporary fetch failures. Error handling exponential backoff (10min→30min→1hour) after repeated failures (3 consecutive) with quarantine stopping polling for permanently broken feeds (404, malformed iCal) preserving last successful state allowing manual updates, host-initiated “Retry Now” bypassing backoff. State machine tracks SYNCING (in-flight)→IN_SYNC (success, <5min)→STALE (>1hour)→FAILED (errors≥3) with per-feed status exposed in host UI enabling transparency about sync reliability vs manual management requirement.
10. Behavioral: Cross-Functional Collaboration Under Uncertainty
Difficulty Level: Medium
Role: Senior Software Engineer / Staff Software Engineer
Source: InterviewQuery, VerveAI Copilot, TryExponent, Glassdoor
Topic: Leadership, Product Thinking
Interview Round: Behavioral / Cross-Functional (45-60 min)
Engineering Domain: Communication & Culture
Question: “Tell me about shipping a feature with incomplete information or conflicting stakeholder requirements. How did you navigate that?” / “Describe a project where you championed Airbnb’s mission (‘belonging anywhere’). How did technical decisions reflect this value?” / “Tell me about a time you failed or received critical feedback. How did you learn from it?”
Answer Framework
STAR Method Structure:
- Situation: Conflicting stakeholder requirements (product speed, legal compliance, infrastructure performance) creating design paralysis
- Task: Clarify underlying goals beyond surface requests, propose phased delivery balancing constraints
- Action: Stakeholder deep-dive revealing true priorities, phased approach (Phase 1 fast+acceptable, Phase 2 optimal), trade-off matrix
- Result: Shipped on deadline, satisfied all core requirements (89% vs 95% baseline, acceptable), zero compliance violations, transparent process
Key Competencies Evaluated:
- Ownership Mindset: Proactive problem-solving vs waiting for direction
- Resilience in Ambiguity: Making decisions with 60% information
- Core Values Alignment: Technical decisions reflecting Airbnb mission
- Cross-Functional Influence: Stakeholder management without authority
Answer
Situation: Building host verification where product wanted 3-week launch increasing signups, legal required identity checks preventing fraud liability, infrastructure needed <500ms SLA avoiding checkout drop-off—initial attempt satisfying all led to paralysis as manual review (24-48h) conflicted with instant verification product wanted. Action: Paused executing stakeholder deep-dive: legal clarified true need was fraud prevention not specific workflow discovering async verification acceptable with risk mitigation; product shared growth metric was “active hosts” not “instant signups” accepting 48h delay if conversion remained high; proposed Phase 1 immediate listing creation with “pending verification” badge (partial trust), async review within 48h upgrading to “verified” (full trust), fraud signals (device fingerprint, photo matching) catching high-risk before external bookings—created trade-off matrix showing instant+risky, slow+safe, phased+balanced options with metrics (conversion impact, fraud projections, effort) enabling data-driven alignment. Outcome: Shipped Week 3 meeting deadline, 48h verification satisfied legal (zero violations 6 months), 89% hosts completed vs 95% baseline (acceptable 6% drop), 0.3% fraud rate matching benchmark, stakeholders felt heard through transparent process not engineering dictating—learning: ambiguity signal not blocker, clarify underlying goals not surface requests, propose incremental wins, make trade-offs explicit enabling collaborative prioritization. Airbnb values: “Champion the mission” by prioritizing host trust (belonging requires safety) over rapid growth accepting slight conversion drop for long-term marketplace integrity reflecting mission alignment in technical trade-offs not just marketing.