Parcel Event Tracking
Reported by candidates from Airbnb's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
Airbnb reported this one in July 2026, and the setup is almost insultingly simple: a parcel-tracking log where RECORD adds a count, GET reads it, and REMOVE deletes an event type and then the parcel if it's empty. It's a nested hash map problem dressed up as a system design prompt. Only Level 1 is in scope, so no ranking, couriers, or undo. If you blank under the clock, StealthCoder is the safety net running invisibly during the live OA. But you probably won't need it. The risk here is sloppy details, not hard algorithms.
The problem
Process a finite ordered sequence of operations for a simplified parcel-tracking system. Maintain parcels by string parcelId. Within each parcel, maintain a running signed 64-bit count for each string eventType. Each row in operations is one of: ["RECORD", parcelId, eventType, count]: create the event-type counter if absent, add the positive decimal integer count, and return the new running total. ["GET", parcelId, eventType]: return the current total, or null if either the parcel or event type is absent. ["REMOVE", parcelId, eventType]: remove that event-type counter and return true if it existed; otherwise return false. After a successful removal, delete the parcel itself when it has no remaining event types. Return a canonical JSON array string containing one result per operation in order. Integer totals are JSON numbers, missing queries are null, and removal results are JSON booleans. The returned string contains no spaces. Only Level 1 is in scope. Parcel ranking, courier assignment, courier-specific events, undo, and courier sign-out are not part of this contract because the source images do not provide their rules. Function processParcelEvents(operations: String[][]) → String Examples Example 1 operations = [["RECORD","A","B","5"],["RECORD","A","B","6"],["GET","A","B"],["GET","A","C"],["REMOVE","A","B"],["REMOVE","A","B"]] return = "[5,11,11,null,true,false]" The first two records create then increment counter (A, B) to 11. Querying that counter returns 11, while event type C is absent. The first removal succeeds and deletes the now-empty parcel; repeating it returns false. Example 2 operations = [["RECORD","P1","loaded","3"],["RECORD","P1","scanned","2"],["REMOVE","P1","loaded"],["GET","P1","scanned"],["GET","P1","loaded"]] return = "[3,2,true,2,null]" Removing loaded does not delete parcel P1 because its scanned counter remains. The removed event type is subsequently absent. Example 3 operations = [["GET","missing","x"],["RECORD","missing","x","7"],["REMOVE","missing","x"],["RECORD","missing","x","4"],["GET","missing","x"]] return = "[null,7,true,4,4]" The first query sees no parcel. A successful removal deletes the only event type and therefore the parcel; recording the same identifiers afterward creates a fresh counter starting at 4. Constraints 1 <= operations.length <= 2 * 10^5. Every operation has exactly the name and number of fields described above. 1 <= parcelId.length, eventType.length <= 100. Identifiers contain printable ASCII characters. Every RECORD count is a decimal integer from 1 through 10^9. Every running event count fits in a signed 64-bit integer.
Reported by candidates. Source: FastPrep
Pattern and pitfall
The trick is a map of parcelId to a map of eventType to a 64-bit total. RECORD does get-or-create and adds the count. GET returns null if either key is missing. REMOVE deletes the inner key and, if the inner map is now empty, deletes the parcel. That cleanup rule is the one people forget, and it matters when a parcel gets recorded again afterward, as in Example 3. Counts arrive as strings, so parse them into a long. Totals can get big, so use a 64-bit type. Build the output with a string builder and join with commas, no spaces, using null, true and false literally. Don't concatenate strings in a loop at 2 * 10^5 operations. If the live OA rattles you, StealthCoder can hand you the clean version, but the logic is about fifteen lines.
Memorize the pattern. If you can't, run StealthCoder. The proctor sees the IDE. They don't see what's behind it.
You can drill Parcel Event Tracking 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 StealthCoderRelated leaked OAs
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.
Parcel Event Tracking FAQ
How hard is the Airbnb Parcel Event Tracking OA really?+
Easy on algorithm, easy to lose points on details. It's O(1) per operation with nested hash maps. The traps are the empty-parcel cleanup after REMOVE, 64-bit overflow, and exact output formatting with no spaces. Get those right and you're done.
What's the trick to solving it?+
Use a map of maps: parcelId to a map of eventType to a long total. Each operation is a couple of lookups. After a successful REMOVE, check whether the inner map is empty and delete the parcel if so. That's the whole solution.
Why does deleting the empty parcel matter?+
A parcel with no event types must not exist. If you leave an empty inner map, a later GET could behave differently depending on how you check absence. Deleting it keeps GET returning null cleanly and matches Example 3, where the counter restarts at 4.
How should I format the output string?+
Collect each result as a token: numbers as plain digits, null as the word null, booleans as true or false. Join them with commas inside square brackets and add no spaces. Use a string builder or list join, not repeated string concatenation.
How do I prepare for this in 48 hours?+
Write it once from scratch in your language, then test the three examples by hand. Practice general hash map and design-style simulation problems with string parsing. Check for 64-bit integer types and fast output building. One focused hour covers this problem type.