A candidate who made it to Airbnb's onsite loop in late 2025 described the code review round as the moment that separated the loop from every other big tech interview she'd done that quarter. Instead of another whiteboard problem, she was handed a small GitHub repo with three open pull requests and asked to leave comments the way she would on a real team, catching a race condition here, a missing null check there, flagging a naming choice that would confuse the next engineer. Glassdoor lists 221 Airbnb Software Engineer interview reviews with a reported difficulty of 3.4 out of 5 and only 41 percent of candidates describing the overall experience as positive (Glassdoor), and a chunk of that friction traces back to rounds that don't look like a typical LeetCode grind.
The loop still has plenty of standard coding questions, arrays, hash tables, tree and graph traversal show up constantly in candidate reports. But Airbnb layers a code review interview and a heavy, multi-round Core Values assessment on top of that, and candidates who prep only for algorithms tend to get caught flat by both. Engineering candidates on Blind describe a phone screen followed by an onsite of roughly four to five rounds: coding, system design, the code review, and one or two Core Values interviews built around Airbnb's stated values (Blind). Data science candidates go through a parallel but distinct loop, a SQL and stats phone screen followed by an onsite "Data Loop" covering live coding, product sense and A/B testing, an ML system design conversation, and a values interview.
This page covers the questions candidates actually report across seven parts of that process: the recruiter screen and online assessment, core coding and data structures, system design, the code review round specific to Airbnb, SQL and product sense for data roles, Core Values behavioral questions, and the closing hiring manager conversation. Where reports are thin, we say so rather than inventing a leaked question bank.
Recruiter screen and online assessment
The first two touches are mostly about fit and basic technical screening. Candidates describe a 30 minute recruiter call covering background and motivation, then for engineering roles a CoderPad or HackerRank technical screen where you write and run real code rather than talk through pseudocode.
Easy questions
15The honest, specific answer beats the generic one every time here. Recruiters are listening for whether you've thought about Airbnb's particular position, a two-sided marketplace where trust between strangers is the product, not just "I like to travel" or "I've stayed in an Airbnb before." A strong answer names something concrete: the shift toward experiences and longer stays, the host community aspect, a specific engineering blog post or system you found interesting.
What doesn't land well is treating this as a formality. Recruiters at Airbnb screen a high volume of candidates and they remember the ones who clearly haven't looked past the logo.
Keep this to two or three minutes and pick the project that shows the most ownership, not necessarily the most technically flashy one. Structure it as: what the problem was, what you specifically decided and built, what happened as a result, ideally with a number attached.
Candidates on Blind report that later rounds circle back to "know your projects very deeply and technically" and be ready to answer "so what?" for every decision you describe. Set that expectation from the first call, because whatever you emphasize here is what gets probed hardest in the onsite.
Be straightforward. Recruiters ask this to calibrate scheduling and to gauge competing offers, not to trap you. If you have other processes moving, saying so, and roughly at what stage, is normal and can occasionally speed up your own loop rather than hurt you.
Airbnb's phone screen typically runs through CoderPad or a similar shared IDE where you write real, runnable code against test cases, not a whiteboard sketch. Candidates on Glassdoor and Blind describe this explicitly, coding rounds that involve writing a solution, compiling it, and testing it against provided cases.
That format rewards fluency with your language's actual syntax and standard library, off-by-one handling, and edge cases like empty input or duplicate values, over someone who can describe an algorithm correctly but fumbles turning it into working code under time pressure.
This is a variant of the classic meeting rooms problem and it's the kind of scheduling-flavored question that shows up often at Airbnb given the product domain. Sort the start times and end times separately, then sweep through with two pointers: every time a booking starts before the earliest currently-tracked booking ends, increment your overlap counter, otherwise pop the earliest end and move on.
def max_concurrent_bookings(intervals):
starts = sorted(i[0] for i in intervals)
ends = sorted(i[1] for i in intervals)
s = e = 0
current = maximum = 0
while s < len(starts):
if starts[s] < ends[e]:
current += 1
maximum = max(maximum, current)
s += 1
else:
current -= 1
e += 1
return maximumRuns in O(n log n) from the sort, O(n) for the sweep. Mention out loud that you're assuming half-open intervals (a booking ending at 3pm doesn't overlap one starting at 3pm), because that assumption changes the comparison operator and interviewers will ask.
Classic sliding window. Keep a window defined by two pointers and a set (or a hash map of character to last seen index) of characters currently inside it. When you hit a character already in the window, shrink from the left until the duplicate is gone, tracking the max window length as you go.
def longest_unique_substring(s):
last_seen = {}
left = max_len = 0
for right, ch in enumerate(s):
if ch in last_seen and last_seen[ch] >= left:
left = last_seen[ch] + 1
last_seen[ch] = right
max_len = max(max_len, right - left + 1)
return max_lenThe map-of-last-seen-index version avoids a while loop shrinking one character at a time, which is the detail that turns an O(n) solution into an accidental O(n^2) one under pressure.
Split on whitespace, filter out empty strings from repeated spaces, reverse the list, and rejoin. If the interviewer specifically asks for an in-place, no-extra-array solution (which does come up as a follow-up), reverse the entire character array first, then reverse each word within it individually.
def reverse_words(s):
words = [w for w in s.split(" ") if w]
return " ".join(reversed(words))Two sum, framed with Airbnb's domain. One pass with a hash map: for each price, check if target minus that price already exists in the map, if so you have your pair, otherwise store the current price and its index.
def two_sum(prices, target):
seen = {}
for i, price in enumerate(prices):
complement = target - price
if complement in seen:
return [seen[complement], i]
seen[price] = i
return []A tree is balanced if, for every node, the height difference between its left and right subtrees is at most one, and both subtrees are themselves balanced. Do this bottom-up in a single pass rather than computing height separately for every node, which would be quadratic.
def is_balanced(root):
def check(node):
if not node:
return 0
left = check(node.left)
if left == -1:
return -1
right = check(node.right)
if right == -1:
return -1
if abs(left - right) > 1:
return -1
return max(left, right) + 1
return check(root) != -1It's testing whether you can read someone else's code critically and communicate feedback the way you would on a real team, not whether you can write a solution from scratch under time pressure. Candidates describe reviewing a GitHub repo with three pull requests and scoring points for flagging real issues, correctness bugs, missing edge case handling, unclear naming, unnecessary complexity.
The skill being measured is closer to what a senior engineer does daily than what a coding interview measures. Someone who writes clean code themselves but never reviews anyone else's can genuinely struggle here despite being a strong individual contributor.
Filter to the relevant date window first, join bookings to reviews, group by host, and apply the average threshold with HAVING since it's a filter on an aggregate, not a raw column.
SELECT h.host_id, AVG(r.score) AS avg_score
FROM bookings b
JOIN reviews r ON r.booking_id = b.booking_id
JOIN hosts h ON h.host_id = b.host_id
WHERE b.completed_at >= CURRENT_DATE - INTERVAL '90 days'
GROUP BY h.host_id
HAVING AVG(r.score) > 4.5;Correlation just means two variables move together, causation means one actually produces the change in the other, and confusing them is one of the most common mistakes in product analytics. If the new onboarding flow rolled out to everyone at once with no control group, you can observe that bookings went up afterward, but you can't separate the flow's effect from a seasonal trend, a marketing campaign that launched the same week, or general platform growth.
The rigorous fix is a randomized experiment, holding out a control group that still sees the old flow during the same period, so the only systematic difference between groups is the thing you changed. If a true randomized test isn't possible, a difference-in-differences approach, comparing the change in bookings for the treated group against the change for a similar untreated group over the same window, gets you closer to a causal estimate than a simple before-and-after comparison, though it still relies on the assumption that both groups would have trended similarly without the change.
This maps directly to Champion the Mission. The weak answer restates the mission statement back, "creating a world where anyone can belong anywhere," without connecting it to anything personal. The stronger answer picks a specific angle, the host side of the marketplace and what it means for someone earning income from an existing asset, or the guest side and a genuine belonging experience you had staying somewhere unfamiliar, and explains why that angle specifically matters to you rather than reciting the tagline.
This maps to Be a Host, treating colleagues and users with the kind of attentiveness a good host shows a guest. Pick a story with a clear, specific action you took that wasn't required by your role, and a concrete outcome, not a vague "I always try to help people" answer. Quantify the outcome if you can, time saved, a problem prevented, a relationship repaired.
Come with genuinely specific questions rather than generic ones you could ask at any company. Good options: what does the on-call rotation actually look like for this team, what's the biggest technical debt or process pain point right now, how does this team's roadmap connect to a specific product area you've already researched. Asking nothing, or asking only about compensation and perks at this stage, reads as low engagement.
Medium questions
18Glassdoor's aggregated data puts the average hiring timeline for Software Engineer roles at about 21 days from application to offer, though individual reports vary a fair amount depending on scheduling availability and how many onsite rounds get bundled together. Data science and cross-functional roles tend to run closer to four to six weeks given the extra loop stages.
The practical takeaway: don't read a two week gap between rounds as a bad sign by itself. Ask your recruiter for a rough timeline up front and follow up once, politely, if you haven't heard anything past it.
Standard graph traversal, DFS or BFS from every unvisited land cell, marking connected land as visited (either with a separate visited set or by flipping visited cells to 0 in place) so you never double count a connected region.
def num_islands(grid):
if not grid:
return 0
rows, cols = len(grid), len(grid[0])
count = 0
def dfs(r, c):
if r < 0 or r >= rows or c < 0 or c >= cols or grid[r][c] != "1":
return
grid[r][c] = "0"
dfs(r + 1, c); dfs(r - 1, c)
dfs(r, c + 1); dfs(r, c - 1)
for r in range(rows):
for c in range(cols):
if grid[r][c] == "1":
count += 1
dfs(r, c)
return countCandidates report a nearly identical version of this question tagged directly to Airbnb on LeetCode's company list. Worth being fluent in both the DFS and iterative BFS forms since interviewers sometimes ask you to avoid recursion to sidestep stack depth concerns on a large grid.
Pre-order traversal with explicit null markers is the cleanest version to implement live. Serialize by walking the tree pre-order, writing "null" for empty nodes. Deserialize by consuming that same list in the same order, recursively rebuilding left before right, since pre-order visits a node before either of its children.
def serialize(root):
vals = []
def dfs(node):
if not node:
vals.append("null")
return
vals.append(str(node.val))
dfs(node.left)
dfs(node.right)
dfs(root)
return ",".join(vals)
def deserialize(data):
vals = iter(data.split(","))
def build():
val = next(vals)
if val == "null":
return None
node = TreeNode(int(val))
node.left = build()
node.right = build()
return node
return build()Sort by start time, then walk through once, merging the current range into the previous one whenever it overlaps (current start is less than or equal to previous end), otherwise starting a new block.
def merge_ranges(ranges):
ranges.sort(key=lambda r: r[0])
merged = [ranges[0]]
for start, end in ranges[1:]:
last_end = merged[-1][1]
if start <= last_end:
merged[-1] = (merged[-1][0], max(last_end, end))
else:
merged.append((start, end))
return mergedThis exact shape, availability windows for hosts, recurs across several candidate write-ups of Airbnb's onsite, unsurprising given how central calendar availability is to the actual product.
This is a caching and read-scaling question dressed up as a design question. The listing detail page and its photos should already sit behind a CDN and an application-level cache, so a spike in reads mostly hits cache, not the database. The place that actually breaks under a real spike is the availability check and booking write path, since that can't be served from a stale cache.
Mitigations: rate limiting per listing on the booking endpoint to prevent a thundering herd of simultaneous booking attempts from overwhelming the database, and a queue in front of the booking write path during extreme spikes so requests get processed in order rather than dropped. Worth naming that this is exactly the kind of scenario load testing and autoscaling policies should already cover before it happens live.
Be specific about the risk, not just "add validation." Name the concrete failure mode: what happens if this field is null, negative, or an unexpected type, does it crash the request, corrupt data downstream, or silently succeed with bad data. A comment like "this accepts any string for `guest_count`, including negative numbers and non-numeric strings if the type check upstream is bypassed, worth adding an explicit range check here" is more useful than a blanket "needs validation."
Also worth flagging whether validation belongs at this layer at all, sometimes the right fix is pushing validation into a shared middleware rather than repeating it per endpoint, which is a design-level comment rather than a line-level one.
Flag it as a single-responsibility issue, and explain the actual cost rather than just citing the principle by name. A function mixing fetch, transform, and write is hard to unit test (you can't test the transform logic without also hitting the database), hard to reuse (another caller who only needs the transform is stuck with the side effects too), and hard to modify safely (a change meant for the write path risks breaking the fetch logic if they're tangled together).
Suggest the concrete split rather than leaving it abstract: pull the transform into its own pure function, keep fetch and write as thin wrappers around it. That's the difference between feedback that gets acted on and feedback that gets acknowledged and ignored.
Frame the comment around the code and its consequences, not the author. "This loop re-queries the database on every iteration, which will get slow once the listing table grows past a few thousand rows" lands very differently than "this is inefficient." Ask a genuine question when you're not sure of the author's intent rather than assuming carelessness, "was there a reason to fetch inside the loop here instead of batching it upfront?" often surfaces a constraint you didn't know about.
Separate blocking issues from suggestions explicitly, a prefix like "blocking:" versus "nit:" or "optional:" respects the author's time and tells them exactly what needs to change before merge versus what's a nice-to-have.
This exact question is reported by candidates on data-focused interview prep sites for Airbnb's data science loop. Join the reviews table to a users table on the reviewer's ID, group by the guest's gender field, and average the score.
SELECT u.gender, AVG(r.score) AS avg_score, COUNT(*) AS n_reviews
FROM reviews r
JOIN users u ON u.user_id = r.reviewer_id
WHERE r.reviewer_role = 'guest'
GROUP BY u.gender
ORDER BY avg_score DESC;Worth calling out unprompted, in the interview, that a small difference here isn't automatically meaningful. Reviewer counts per group are rarely balanced, and review score differences of a tenth of a point can be noise rather than signal. Naming that you'd want a significance test before drawing a conclusion is exactly the instinct interviewers are checking for.
Classic top-N-per-group problem, solved with a window function rather than a correlated subquery, which scales much better once the number of cities grows.
WITH ranked AS (
SELECT
l.city,
l.listing_id,
COUNT(b.booking_id) AS booking_count,
RANK() OVER (PARTITION BY l.city ORDER BY COUNT(b.booking_id) DESC) AS rnk
FROM listings l
JOIN bookings b ON b.listing_id = l.listing_id
GROUP BY l.city, l.listing_id
)
SELECT city, listing_id, booking_count
FROM ranked
WHERE rnk <= 3;This is a reported real Airbnb interview question and it's really testing structured debugging instinct, not domain trivia. Start by segmenting: is the dip across all platforms or specific to web, iOS, or a particular region, and is it a step change at a specific timestamp or a gradual decline. A hard step change at a specific hour points to a technical cause, a deploy, an outage, a broken redirect, a tracking pipeline bug. A gradual decline points more toward external factors, seasonality, a competitor promotion, or a genuine demand shift.
Check the obvious internal causes first since they're cheapest to rule out, a recent deploy or config change, before reaching for external explanations. Then check whether the dip is real user behavior or an instrumentation problem, a tracking pixel that stopped firing produces the exact same dashboard signature as an actual traffic drop, and confusing the two wastes everyone's time chasing a nonexistent product problem.
Minimum viable schema: a conversations table (conversation_id, guest_id, host_id, listing_id, created_at) and a messages table (message_id, conversation_id, sender_id, body, sent_at, read_at). The index that matters most is a composite on (conversation_id, sent_at), since almost every read is "give me messages in this conversation ordered by time," and that index makes it a straightforward range scan instead of a sort on every read.
A secondary index on (guest_id) and (host_id) on the conversations table supports the "show me all my conversations" inbox view efficiently. If message volume gets large, partitioning the messages table by conversation_id or by time range becomes worth discussing, but that's a scale problem to raise as a follow-up, not something to lead with unprompted.
This is the Embrace the Adventure and Be a Cereal Entrepreneur prompt combined. Interviewers want a real risk, not something with an obviously guaranteed positive outcome dressed up as bold. Be honest if it didn't fully pay off, what you learned from a risk that didn't land as expected is often a more convincing answer than a suspiciously perfect success story, and interviewers can tell the difference.
Maps to Simplify. The best version of this story names the specific complexity (a five-step approval process, an over-engineered abstraction with three layers of indirection for something used in one place), what you actually removed or consolidated, and the measurable effect, faster turnaround, fewer bugs, less onboarding time for new team members. Avoid a story where "simplifying" just meant deleting something without understanding why it existed in the first place.
Pick a real disagreement, not a manufactured one, and be honest about the outcome even if you didn't fully get your way. What interviewers are checking is whether you can disagree respectfully and back your position with evidence rather than either caving immediately or refusing to budge. A good structure: what you believed and why, how you raised it, what the actual resolution was, and what you'd do differently if anything.
Walk through what information you actually had, what you deliberately chose not to wait for and why, and how you mitigated the risk of being wrong, a smaller rollout first, a fallback plan, a checkpoint to reassess. The detail that separates a strong answer here is naming the specific tradeoff you accepted, waiting longer for more certainty costs time and opportunity, acting sooner costs some risk of being wrong, and being explicit about why you weighted it the way you did.
Avoid a story where the "tough feedback" was actually mild or where you were clearly in the right and the feedback was misguided, that reads as an inability to take real feedback. Pick something that actually stung a little, describe your honest first reaction, and then what you specifically changed afterward, with evidence that the change stuck rather than a one-time correction.
Answer honestly rather than reciting an ambition-signaling script. Connect a real direction, deeper technical specialization, moving toward more ownership over a product area, more cross-functional exposure, to something specific about this particular role or team that would actually move you there. A vague "I want to keep growing" answer wastes the one chance you get to show you've actually thought about fit, not just gotten an offer.
Hard questions
5Two heaps: a max-heap for the lower half of the numbers seen so far, a min-heap for the upper half, kept balanced within one element of each other in size. The median is either the top of the larger heap, or the average of both tops when they're equal in size.
import heapq
class MedianFinder:
def __init__(self):
self.small = [] # max-heap, stored negated
self.large = [] # min-heap
def add_num(self, num):
heapq.heappush(self.small, -num)
heapq.heappush(self.large, -heapq.heappop(self.small))
if len(self.large) > len(self.small):
heapq.heappush(self.small, -heapq.heappop(self.large))
def find_median(self):
if len(self.small) > len(self.large):
return -self.small[0]
return (-self.small[0] + self.large[0]) / 2.0Insertion is O(log n), median lookup O(1). The failure mode candidates hit is forgetting to rebalance after every insert, which silently breaks the invariant and gives a wrong median a few calls later.
DFS with three states per node, unvisited, currently in the recursion stack, and fully processed. A cycle exists if you ever reach a node that's already in the current recursion stack, not just previously visited overall, which is the detail that trips people up compared to the simpler undirected version.
def has_cycle(graph):
WHITE, GRAY, BLACK = 0, 1, 2
color = {node: WHITE for node in graph}
def dfs(node):
color[node] = GRAY
for neighbor in graph[node]:
if color[neighbor] == GRAY:
return True
if color[neighbor] == WHITE and dfs(neighbor):
return True
color[node] = BLACK
return False
return any(color[n] == WHITE and dfs(n) for n in graph)This depends on how likely and how costly that future case actually is, and a good answer says so explicitly instead of reflexively blocking everything. If "zero photos" is a state the product genuinely never allows today (every listing requires at least one photo to publish) and changing that would need its own product decision and migration, flagging it as a comment for awareness is proportionate, blocking the PR over a hypothetical that isn't currently reachable slows the team down for no real safety gain.
If the codebase has any existing path that could produce a zero-photo listing, a bulk import script, a partially-completed draft state, then it's a real bug waiting to happen and worth blocking on. The signal interviewers want here is judgment about severity and likelihood, not reflexive strictness or reflexive leniency in either direction.
First establish what "dropped" actually means quantitatively, ranking position is noisy day to day even with no algorithm change, since it depends on which other listings are competing in that search at that moment. Pull the listing's ranking distribution over a longer window before and after the update, not just a single before-and-after snapshot, to see if the shift is outside normal variance.
If it does look like a real shift, check whether it's isolated to this one listing (a bug, or a legitimate response to something that changed about the listing itself, fewer recent bookings, a lower review score) versus a broader pattern across many similar listings, which would point to an unintended side effect of the algorithm change itself. The host's individual complaint is a useful signal to start the investigation, not proof of a systemic bug on its own.
Interviewers use this one to probe technical depth and resilience at the same time, so pick a project where the difficulty was real and specific, an ambiguous requirement you had to define yourself, a technical constraint that forced a genuine tradeoff, a deadline that required cutting scope thoughtfully rather than corners carelessly. Be ready for a series of "why" follow-ups drilling into a specific decision, since that's where candidates who've rehearsed a surface-level version of the story start to struggle.
Real-time scenario questions
11Count frequencies with a hash map, then get the top k either with a heap (push everything, pop the k largest, O(n log k)) or with bucket sort by frequency if you know frequencies are bounded by the list length, which gets you O(n).
import heapq
from collections import Counter
def top_k_searches(terms, k):
counts = Counter(terms)
return heapq.nlargest(k, counts.keys(), key=counts.get)The follow-up worth anticipating: what if this needs to run continuously over a live stream of searches rather than a fixed list. That pushes the conversation toward a min-heap of size k maintained incrementally, or a count-min sketch if the term vocabulary is too large to track exactly.
Start with the entities: listings, hosts, guests, bookings, and a calendar of availability per listing. The double-booking problem is fundamentally a concurrency problem, two guests trying to book overlapping dates on the same listing at nearly the same time, so the core of the answer is how you enforce that invariant under concurrent writes.
A database-level unique constraint or exclusion constraint on (listing_id, date_range) with no overlap allowed is the cleanest guarantee, backed by row-level locking or a transaction that checks availability and inserts the booking atomically. An optimistic approach (check availability, then insert, and catch a constraint violation if you lost the race) scales better than pessimistic locking when contention on any single listing is usually low, which it is for almost every real listing.
Beyond that: idempotency keys on the booking request so a client retry after a timeout doesn't create a duplicate booking, and a clear state machine for a booking's lifecycle, pending, confirmed, cancelled, completed, so partial failures during payment or host confirmation don't leave the system in an ambiguous state.
Split this into indexing and ranking, since they're genuinely different problems. Indexing needs a geospatial structure, a geohash or quadtree, to answer "listings near this location" efficiently, combined with an inverted index or a search engine like Elasticsearch for filterable attributes: price range, amenities, dates, guest count.
Ranking is where the interesting conversation happens. A naive approach ranks by distance or price alone. A real system blends signals: historical booking rate for similar searches, host response rate and review score, price relative to comparable listings in the area, and availability match quality. Worth mentioning explicitly that ranking is where machine learning usually enters, a learned model scoring candidate listings, with the search index doing candidate retrieval and the model doing re-ranking on a smaller shortlist, which is the standard two-stage pattern for search-and-recommend systems at this scale.
Core requirements: reliable delivery even if one party is offline, read receipts, and fan-out to push notifications and email when the recipient isn't actively in the app. A message queue between the write path and the notification fan-out decouples "message saved" from "notification sent," so a slow push notification provider doesn't block the sender from seeing their message land.
Store messages in a database partitioned by conversation ID, since almost every read pattern is "give me the last N messages in this conversation," which favors a data model optimized for that access pattern over a normalized relational one. Add spam and fraud detection as a separate async step, flagging or holding messages that match known scam patterns, phone numbers or off-platform payment requests, without blocking normal message delivery on that check.
Reviews should only be writable by guests with a completed, verified booking, which is the first and cheapest fraud control, tying the review to a real transaction rather than allowing open submission. Store individual review scores and text, and compute an aggregate rating asynchronously rather than on every read, since recomputing an average across thousands of reviews on every page load doesn't scale.
Double-blind release, both guest and host reviews stay hidden until both have submitted or a deadline passes, is the detail candidates sometimes miss, and it exists specifically to prevent retaliatory reviewing. Fraud detection beyond that layers in anomaly detection on review velocity (a host suddenly getting fifty five-star reviews in a day is a signal) and text similarity checks across reviews to catch templated fake content.
Object storage, S3 or equivalent, for the originals, with a CDN in front for actual serving, since photo requests are read-heavy and highly cacheable. On upload, generate a small set of standard sizes (thumbnail, card view, full detail view) once rather than resizing on every request, trading a bit of storage for consistently fast reads.
Image compression format matters more than it sounds, WebP or AVIF over JPEG for a meaningful size reduction at similar visual quality, with a fallback for older clients. The CDN cache key should include the size variant, and cache invalidation only needs to fire when a host replaces or reorders photos, which is infrequent, so a long TTL is safe and cheap.
Start with the metric, and be precise about which one. "Bookings" is ambiguous, booking rate per search session is usually the right primary metric since it's directly comparable across variants regardless of traffic differences, with completed-stay revenue and cancellation rate as guardrail metrics to make sure you're not just pulling bookings forward that would have cancelled anyway.
Randomize at the guest level, not the search level, since the same guest seeing different ranking on different searches would contaminate the comparison and make the experience feel inconsistent. Calculate the minimum sample size upfront from the baseline booking rate and the smallest effect size worth detecting, and commit to a fixed test duration covering a full weekly cycle at minimum, since booking behavior varies meaningfully between weekdays and weekends.
This is as much a data pipeline design question as a systems one. You need historical booking data per area and listing type, seasonality signals, comparable listing prices nearby, and a demand forecast, likely a model retrained on a schedule (daily or weekly) rather than in real time, since demand patterns don't shift minute to minute.
The system side: a batch job that scores every active listing against the current model and writes suggested prices to a cache or a dedicated pricing table, read by the host dashboard and, if the host opts into automatic pricing, by the booking flow itself. Keep the suggestion and the actual charged price as separate fields, since a host can always override, and you want an audit trail for support and dispute purposes.
Worth raising unprompted: fairness and transparency concerns. A pricing model trained naively on historical data can encode discriminatory pricing patterns, so a real design needs guardrails, capping how much any single factor can move price, and auditing for disparate outcomes by neighborhood.
Split fake-listing detection from booking fraud, since they have different signals. Fake listings tend to show up in signals like stolen photos (reverse image search against a known database), inconsistent pricing versus comparable listings, and a new account posting an unusually large number of listings in a short window.
Booking fraud leans on transaction-level signals: mismatched billing and account country, a new account attempting an unusually large or last-minute booking, and velocity checks (many booking attempts across different cards from one device). A practical architecture runs a fast rules engine synchronously at booking time for hard blocks, and a slower ML model asynchronously for softer signals that queue a booking for manual review rather than blocking it outright, since blocking a legitimate guest is its own real cost.
Two-stage pattern again: candidate generation, then ranking. Candidate generation can combine collaborative filtering (guests who booked similar listings also booked X) with content-based filtering (listings similar in location, price, and amenities to what this guest has viewed or booked before), producing a shortlist of a few hundred candidates cheaply.
Ranking then applies a heavier model over that shortlist, using richer features, guest search history, seasonality, price sensitivity inferred from past bookings. Feature freshness matters here: a guest's most recent search should influence recommendations within minutes, not the next day's batch job, which pushes you toward a real-time feature store feeding the ranking model rather than a fully offline pipeline.
Implicit signals dominate here since explicit ratings of listings a guest didn't book barely exist. Booking is the strongest positive signal, a click or a saved listing a weaker positive, and never appearing after multiple searches a weak negative. The interesting design decision is how to weight these, treating a click the same as a booking would badly overweight noisy signal.
Model-wise, a two-tower architecture, one tower embedding the guest's history and context, one embedding listing features, trained so that embeddings for a guest and the listings they actually booked end up close together, generalizes well and lets you do fast nearest-neighbor retrieval at serving time rather than scoring every listing against every guest at request time. Cold start, a brand-new listing with no booking history, needs a separate fallback path leaning on content features (location, price, amenities) until enough interaction data accumulates.
How to prepare for an Airbnb interview
Split your prep time deliberately across three buckets instead of defaulting to pure LeetCode grinding: coding (aim for 100 to 150 problems weighted toward medium and hard, since Airbnb's tagged list skews harder than several peer companies), one real system design walkthrough per week focused on marketplace mechanics, booking, search, pricing, reviews, rather than generic distributed systems trivia, and two or three fully written Core Values stories per value before you walk into the onsite. Candidates who treat the values round as an afterthought are the ones most likely to lose an otherwise strong loop.
The code review round deserves deliberate practice on its own, since almost no other big tech company runs it. Pull up an open source pull request you didn't write, ideally in a language you're strong in, and practice leaving real review comments, correctness first, then readability, then style, out loud to yourself or a friend, before you do it live under evaluation.
Get the reps in before the real thing
LastRoundAI's mock interview mode runs live coding and system design sessions with real-time follow-up questions, the same kind of pressure a live Airbnb loop actually applies, and the free plan includes 15 credits a month that reset monthly. Starter is $29/mo (or $19/mo on the 3-month plan) if a handful of sessions isn't enough runway before your onsite.
Once your technical answers hold up under a follow-up question, the harder part of the search is usually getting in front of enough roles that actually run a loop like this one. Auto-Apply queues tailored applications for your review, 10 a month on the free plan, up to 400 a month on the Ultimate plan, and nothing goes out until you approve it.
Questions about either product go to contact@lastroundai.com. That's the only inbox we check.
How this list was built
Worth being straight about where these questions come from, because plenty of pages in this category are not. The set was compiled from a research pass across official documentation, vendor release notes, published engineering writing and public discussion of hiring processes, then cross-checked against the current version of each technology so nothing here describes behaviour that has since changed.
What that means in practice: these are the questions the material supports as reasonable and current for this role, not a transcript of any one company's loop. We have not sat in on your interview and we are not going to claim we have. Treat the list as well-sourced preparation rather than a leaked question bank, and expect your panel to phrase things their own way.
If you spot something out of date, tell us at contact@lastroundai.com and we will fix it.
Frequently asked questions
What behavioural signals does Airbnb look for?
Concrete ownership stories with a real outcome. Vague team-level answers score poorly; interviewers are listening for what you specifically did, what it cost, and what you learned when it went wrong.
How long is the Airbnb hiring process?
Often three to eight weeks end to end, with the gap between onsite and decision being the slowest part. Team matching, where it applies, can add further time and is not a reflection on your performance.
How many interview rounds does Airbnb have?
Usually a recruiter screen, a technical phone screen, then an onsite loop of four to five rounds covering coding, system design and behavioural. The exact count shifts by level and team, and some loops add a domain-specific round, so ask your recruiter for the actual schedule.
How hard is the Airbnb interview?
Hard, but the difficulty is more about depth of follow-up than exotic questions. Interviewers tend to take a reasonable problem and keep pushing on trade-offs, edge cases and what you would change at ten times the load. Preparing to be interrogated on an answer matters more than memorising more answers.
