Reported September 2026
Airbnbdesign

Progressive Banking System

Reported by candidates from Airbnb's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.

Get StealthCoderRuns invisibly during the live Airbnb OA. Under 2s to a working solution.
Founder's read

Airbnb reportedly put this one in front of candidates in September 2026, and it's a design problem wearing a banking costume. Eight operations, one stream of queries, and a scheduled-payment queue that fires before every external query. The whole solution hinges on one data structure choice: a min-heap keyed on (due time, creation order) for pending payments, sitting next to per-account balance history. If you blank on how the pieces fit together, StealthCoder is the safety net running invisibly during the live OA. Read on for the shape of the solution.

The problem

Process queries in order. Each query contains an operation name followed by a strictly increasing non-negative timestamp and its arguments. Before processing an external query at timestamp t, execute every pending scheduled payment whose due time is at most t, ordered by due time and then payment creation order.
Return one string per external query, in order. Supported operations are:
["CREATE_ACCOUNT", t, account]: create an account with balance and outgoing total zero. Return true, or false if the active account already exists.
["DEPOSIT", t, account, amount]: add a positive amount. Return the new balance, or the empty string when the account is absent.
["TRANSFER", t, source, target, amount]: move a positive amount between two distinct active accounts. Return the source balance after success, or the empty string when either account is absent, the accounts are equal, or funds are insufficient. A successful transfer adds the amount to the source account's outgoing total.
["TOP_SPENDERS", t, n]: among active accounts, return at most n entries formatted account(outgoing), ordered by outgoing total descending and account identifier ascending, joined by commas.
["SCHEDULE_PAYMENT", t, account, amount, delay]: schedule a positive payment for time t + delay, where delay is positive. If the account exists, return the next global identifier paymentK; otherwise return the empty string and do not consume an identifier.
["CANCEL_PAYMENT", t, account, paymentId]: cancel a pending payment only when it currently belongs to that active account. Return true on success and false otherwise. A payment due at t is processed before this cancellation query.
["MERGE_ACCOUNTS", t, survivor, absorbed]: merge two distinct active accounts. The survivor receives the absorbed balance and outgoing total; pending payments of the absorbed account now belong to the survivor; and the absorbed account closes at t. Return true on success and false otherwise.
["GET_BALANCE", t, account, timeAt]: return that account's balance immediately after all activity at timestamp timeAt, or after the latest earlier activity when none occurred exactly then. Return the empty string if the account did not exist at that time. The requested time satisfies 0 <= timeAt <= t.
When a scheduled payment becomes due, deduct it only if its current account is active and has enough funds. A successful payment adds to outgoing total. Whether it succeeds or not, it is no longer pending. Balances and totals fit in signed 64-bit integers.

Function
processBankingQueries(queries: String[][]) → String[]

Examples
Example 1
queries = [["CREATE_ACCOUNT","1","alice"],["CREATE_ACCOUNT","2","bob"],["DEPOSIT","3","alice","100"],["TRANSFER","4","alice","bob","30"],["TOP_SPENDERS","5","2"]]
return = ["true","true","100","70","alice(30),bob(0)"]
The transfer leaves alice with 70 and records 30 of outgoing activity, so she ranks before bob.
Example 2
queries = [["CREATE_ACCOUNT","1","a"],["DEPOSIT","2","a","50"],["SCHEDULE_PAYMENT","3","a","20","5"],["GET_BALANCE","7","a","7"],["GET_BALANCE","8","a","8"],["CANCEL_PAYMENT","9","a","payment1"]]
return = ["true","50","payment1","50","30","false"]
The payment is still pending at timestamp 7. It executes before the query at timestamp 8, so cancellation afterward fails.
Example 3
queries = [["CREATE_ACCOUNT","1","a"],["CREATE_ACCOUNT","2","b"],["DEPOSIT","3","a","10"],["DEPOSIT","4","b","25"],["SCHEDULE_PAYMENT","5","b","5","5"],["MERGE_ACCOUNTS","6","a","b"],["GET_BALANCE","7","b","5"],["GET_BALANCE","8","b","6"],["GET_BALANCE","10","a","10"]]
return = ["true","true","10","25","payment1","true","25","","30"]
Account b exists with balance 25 before the merge but is closed at timestamp 6. Its pending payment follows the survivor and reduces the combined balance from 35 to 30 at timestamp 10.

Constraints
1 <= queries.length <= 2 * 10^4.
External query timestamps are strictly increasing integers from 0 through 10^9.
Every query has exactly one valid operation shape described above.
Account identifiers are non-empty printable ASCII strings without commas or parentheses.
Amounts and delays are positive integers, and every arithmetic result fits in a signed 64-bit integer.
1 <= n <= 10^5 for TOP_SPENDERS.

Reported by candidates. Source: FastPrep

Pattern and pitfall

Start every query by draining the heap: pop while due time <= t, in (due, creation id) order. That's the ordering rule, and it's the first thing people miss. For each popped payment, check the payment's current owner, because MERGE_ACCOUNTS reassigns ownership. Cancelled payments should be lazily skipped, so keep a payment map with status and owner. GET_BALANCE with timeAt needs history, so store a per-account list of (timestamp, balance) and binary search it. Closed accounts need a close time, so absent-at-time returns empty. TOP_SPENDERS can just sort active accounts, since n and query count are small enough. The pitfalls are the merge edge cases, a payment due exactly at t running before CANCEL_PAYMENT, and not consuming a payment id on failed scheduling. If the live OA scrambles your plan, StealthCoder can hand you a working structure fast.

Memorize the pattern. If you can't, run StealthCoder. The proctor sees the IDE. They don't see what's behind it.

If this hits your live OA

You can drill Progressive Banking System cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Made by an engineer who treats the OA as theater. If yours is tonight, you don't have time to grind. You have time to hedge.

Get StealthCoder

Related leaked OAs

⏵ The honest play

You've seen the question. Make sure you actually pass Airbnb's OA.

Airbnb reuses patterns across OAs. Made by an engineer who treats the OA as theater. If yours is tonight, you don't have time to grind. You have time to hedge. Works on HackerRank, CodeSignal, CoderPad, and Karat.

Progressive Banking System FAQ

What's the core trick in Progressive Banking System?+

Process due payments from a min-heap before every external query, ordered by due time then creation id. Keep accounts in a hash map, payments in a separate map with owner and status, and per-account balance history for time-based lookups.

How do I handle MERGE_ACCOUNTS with pending payments?+

Don't move heap entries. Store the owner on each payment record and reassign owner from absorbed to survivor on merge. When a payment pops, look up its current owner and check that account is active before deducting.

How should GET_BALANCE with timeAt work?+

Append a (timestamp, balance) entry to the account's history on every change, including payment executions and merges. Then binary search for the last entry at or before timeAt. Return empty if timeAt is before creation or at or after closure.

Is this design-style OA still being asked at Airbnb?+

It was reported for Airbnb in September 2026, and multi-operation stateful systems like this are a common format. Expect the same shape with different operations, so practice building the dispatcher plus helper structures rather than memorizing this exact banking story.

How do I prepare in 48 hours?+

Write a clean dispatcher and implement the three examples as tests. Practice a heap with lazy deletion, history lists with binary search, and tie-break sorting. Test the edge cases: payment due exactly at t, cancel after execution, failed schedule not consuming an id.

Problem reported by candidates from a real Online Assessment. Sourced from a publicly-available candidate-aggregated repository. Not affiliated with Airbnb.

OA at Airbnb?
Invisible during screen share
Get it