Software Engineers at eBay build and run the backend systems behind the marketplace: buyer discovery and search, bidding, seller tools, trust and safety, and payments. Reported teams include core search, marketplace seller tools, payments, advertising systems and eBay Live. The reported work includes modernizing older service architectures, migrating services to cloud-native infrastructure, and building backend microservices where event-driven messaging, distributed data consistency and high-concurrency transactions are everyday problems.
Stacks named for the role include Java with Spring Boot, C++, Node.js and Python. Kafka or SQS, Redis, Docker, Kubernetes, AWS, React and GraphQL are listed as nice-to-have experience. Which of these matters depends on the team, so read the posting for your specific seat and prepare in the language that team uses rather than the one you like best.
For interview preparation, this breaks into four areas of work. First, reported coding questions are data-structure problems such as sliding windows, top-K frequency, sorted-matrix search and grid connected components. Second, object-oriented and low-level design, for example an LRU cache with TTL expiry, a contiguous block allocator, an org-chart traversal N levels down and a chess domain model. Third, system design prompts shaped like commerce problems: an order pipeline that survives flash-sale peaks, a live-commerce platform with chat and synchronized bidding, and an ATM backend. Fourth, behavioral prompts that centre on production incidents, technical disagreements and trading deadlines against technical debt.
Initial Screening Call
reportedCandidates describe this stage as a call to assess fit for the role. Ask the recruiter whether your first stage is that fit call, an online assessment or a live technical screen, because each needs different preparation. The Software Engineer title spans several reported teams (core search, seller tools, payments, advertising, eBay Live) and several stacks (Java and Spring Boot, C++, Node.js, Python). Use the call to find out which team and stack the seat belongs to. Then say plainly which parts of it you have done in production and which you have not.
What to demonstrate
- Whether your professional experience lines up with the requirements of the specific posting rather than with the role title in general
- Whether you can describe a backend service you built, including what it did, what you owned and what you would change
- Whether what you want next matches the team the seat sits on
How to prepare
- Mark each line of the posting as done, adjacent or new, and write one sentence per adjacent line naming the closest thing you actually built
- Prepare short answers to common behavioral prompts such as why this company, why you are leaving your current role, and the services you built and what you learned from them
- Ask the recruiter what the next stage looks like: an online assessment or a live interview, which languages are allowed, and what editor or environment you will code in
Technical Interviews
reportedCandidates describe these as multiple interviews covering coding skills and system design. The reported questions fall into three categories, and each needs its own preparation. Data-structure problems test choosing the right structure and stating complexity. Object-oriented and low-level design problems test turning requirements into classes, state and tests. System design prompts test architecture and trade-offs under load. Write runnable code with real names, edge-case handling and explicit test cases rather than pseudocode. In design, fix scale, read and write ratios and availability needs before you draw anything.
What to demonstrate
- Whether your coding solution is correct on boundary inputs (empty, single element, duplicates) and whether you can state its time and space complexity
- Whether a low-level design keeps state consistent: eviction and expiry in a cache, allocation and freeing in an allocator, thread safety where state is shared
- Whether a system design handles the stated load with explicit choices on data store, caching, messaging and consistency, and whether you can say what each choice costs
- Whether you explain your reasoning out loud and use hints rather than defending against them
How to prepare
- Solve the reported coding questions from a blank file: longest substring without repeats, top-K frequent elements, search in a row- and column-sorted matrix, grid connected components, and restoring an array from its adjacent pairs
- Implement an LRU cache with TTL expiry and a contiguous block allocator, each with a small test suite covering eviction order, expired reads, fragmentation and double free
- Work through the reported design prompts with requirements first: a flash-sale order pipeline, a live-commerce platform with synchronized bidding, and an ATM backend with balance, cash dispensing and ledger updates
- Prepare to explain Kafka-style asynchronous messaging, cache invalidation, database connection pooling and race-condition prevention, since these appear among the reported design questions
Behavioral Interviews
reportedCandidates describe this stage as behavioral interviews that assess fit alongside technical skill. The reported prompts are engineering stories: a production defect or outage you diagnosed under pressure, an architectural disagreement, pushing back on scope when deadlines collided with technical debt, and requirements that changed partway through development. Your first answer mostly earns the follow-ups, and the follow-ups carry the interview. A story you can only tell at one level of detail falls apart by the third "why". Prepare four or five projects you can explain down to the code you changed and the argument you had about it, rather than one rehearsed answer per prompt.
What to demonstrate
- Whether a story holds up as the questions move from what you did, to why you chose it over the alternative, to what you would change now
- Whether you can adapt one project to answer the question actually asked, instead of delivering a rehearsed block that answers a nearby one
- Whether you show ownership in a disagreement or incident: the decision you made, the evidence you used and how it was resolved
How to prepare
- Pick four projects and write out four levels for each: what you did, why that, why not the alternative, and what would have had to be true for the alternative to win. If you cannot reach the fourth level, that project is not ready yet
- Map the reported prompts to your projects in advance: an outage you resolved, an architectural conflict, pushing back on scope versus technical debt, changing requirements, and tough feedback you received
- Have someone ask why three times in a row on one thread and note where you start repeating yourself; that is where you need more detail
7 candidate reports. Individual accounts describe a particular role and hiring cycle.
eBay Software Engineer Interview Experience — An Onsite With No LeetCode
This was the most unusual interview I have had so far. There was not a single LeetCode question in the onsite. First round I wrote a shopping cart. There was not much algorithm work, and it felt as though the round was testing how I communicated with the interviewer. Second round I was asked basic questions about data structures and complexity, including very basic topics such as lists, hashes, a…
Read full experienceeBay Software Engineer Online Assessment Experience — Four CodeSignal Questions in 70 Minutes
View report detailseBay Software Engineer Interview Experience — AI-Coding Phone Screen, Rejected After Onsite Coding Round
In June, an HR person reached out about an MTS role, and we talked through some behavioral questions and my project experience. Phone screen: AI coding — basically they give you some code and have you spot design pattern issues (like something not being extensible), or point out a bad data type. On CodeSignal, the AI is really strong and basically does the work for you. You just need to talk thro…
Read full experienceeBay Software Engineer Interview Experience — Three Onsite Rounds With Two System Designs
Round 1 Given an array heights, where each element represents the height of a vertical line. Choose two lines to act as the walls of a container. Return the maximum amount of water the container can hold (max area). Given an array of integers temps representing daily temperatures, write a function to calculate, for each day, how many days you'd have to wait until a warmer temperature. The functio…
Read full experienceeBay Intern Data Analyst Interview Experience — Three SQL-Heavy Phone and Video Rounds
View report detailsPracHub editorial advice for the preparation topics above.
Building a plain LRU cache and treating TTL expiry as an afterthought
In the reported LRU-with-TTL design, expiry changes the semantics: a get on an expired key must behave as a miss and remove the entry, and expired entries should not push live ones out when the cache is full. Keep the O(1) hash map plus doubly linked list for recency, store an expiry time per entry, check it on every read, and say how you reclaim expired entries that are never read again (a periodic sweep or a min-heap keyed by expiry). Write tests for a read exactly at the expiry time, an update that refreshes both value and TTL, and eviction when the cache is full of expired entries.
Answering top-K frequent elements with a full sort and no word on the cost
Counting with a hash map and then sorting every distinct element is O(n log n). State that first, then improve it: a min-heap of size k gives O(n log k), and bucketing elements by frequency gives O(n) because no frequency can exceed n. Say how you break ties and what you return when k is larger than the number of distinct elements. Apply the same habit to the other reported coding questions: a sliding window with last-seen indexes for the longest substring, and a top-right staircase walk for O(m + n) search in the sorted matrix.
Drawing boxes for the flash-sale order pipeline before deciding how inventory stays correct
The hard part of a reported prompt like this is selling no more units than exist while traffic spikes, not the number of services. Fix the numbers first: peak orders per second, how many units are in stock, and whether a user may see stock that has already sold out. Then choose where the decrement happens (an atomic conditional update or a reservation with expiry), put the order request on a queue so the spike is absorbed rather than forwarded to the database, and make order creation idempotent so client retries do not create duplicate orders. Name what you drop under load, such as recommendations or non-essential writes.
Claiming the whole stack at the screening call
The role lists Java and Spring Boot, C++, Node.js and Python across different teams, plus Kafka, Redis, Docker and Kubernetes as nice-to-haves. Anything you claim at the screen can come up again in the technical interviews, so claim only what you can defend. Name the language you will code in, the parts of the stack you have run in production, and the ones you have only read about, and ask which team the seat belongs to so the rest of your preparation targets the right domain.
Telling an architectural disagreement story with no decision and no evidence
Reported behavioral prompts include how you handle architectural conflicts and when you pushed back on scope against technical debt. A story that ends with "we talked it through and agreed" gives the interviewer nothing to follow up on. Say what each side argued for, what evidence you brought (a benchmark, an incident, a cost estimate), who made the final call, and what happened afterwards, including if you turned out to be wrong.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Solve graph traversal and connected component problems, such as identi…
Solve graph traversal and connected component problems, such as identifying matrix regions or grid boundaries.
Approach
- Choose the data structure from the access pattern, not from familiarity.
- Name the brute-force solution and its complexity before improving on it.
- Walk one small example through your approach before writing the whole thing.
Follow-up
- How does this change if the input no longer fits in memory?
- Which test case would catch an off-by-one here?
Determine the length of the longest substring without repeating charac…
Determine the length of the longest substring without repeating characters in a given string.
Approach
- Walk one small example through your approach before writing the whole thing.
- Choose the data structure from the access pattern, not from familiarity.
- Name the brute-force solution and its complexity before improving on it.
Follow-up
- What is the worst case, and how likely is it on real data?
- How does this change if the input no longer fits in memory?
Given a collection of items, find the top $K$ frequent elements using …
Given a collection of items, find the top $K$ frequent elements using an optimal data structure.
Approach
- Name the brute-force solution and its complexity before improving on it.
- State the target complexity and say which constraint rules the naive version out.
- Restate the input: its shape, its size, and what is guaranteed about it.
Follow-up
- Which test case would catch an off-by-one here?
- How does this change if the input no longer fits in memory?
Perform an efficient target search in a 2D matrix where rows and colum…
Perform an efficient target search in a 2D matrix where rows and columns maintain sorted properties.
Approach
- Choose the data structure from the access pattern, not from familiarity.
- State the target complexity and say which constraint rules the naive version out.
- Name the brute-force solution and its complexity before improving on it.
Follow-up
- Which test case would catch an off-by-one here?
- How does this change if the input no longer fits in memory?
Why the naive proximity scan fails at market scale
provider_presence holds 120,000 rows for one dense market, with lat, lon, cell_id, status and expires_at. The dispatch loop runs every 500 ms and, for each of up to 400 open requests, needs the ten nearest idle providers within 3 km. The obvious implementation computes a great-circle distance for every row and sorts. It returns the correct answer. Quantify why it cannot be shipped, give a design that holds a p99 under 30 ms, and state precisely what that design gives up.
Approach
- Cost it in numbers, not adjectives: 400 requests times 120,000 rows is 48 million distance evaluations per cycle, and at a 500 ms cadence that is 96 million per second, plus 400 sorts of 120,000 elements. The defect is not that the haversine formula is slow; it is that the work per request is proportional to fleet size while the whole dispatch budget is a couple of seconds end to end.
- Explain why no B-tree rescues it. The predicate is a function of two columns, so an index on lat, or a composite on (lat, lon), can restrict only the leading column and the rest is a filter. A degree bounding box is index-assisted on that leading column but over-selects: the square circumscribing a circle of radius r has area 4r^2 against the circle's pi*r^2, so under locally uniform density about 21 percent of the rows that survive the box fall outside the radius, (4 - pi)/4, and still need an exact second pass. Keep the two ratios apart: 4/pi - 1, about 27 percent, is how much more area the box covers than the circle — the extra work done, not the false-positive share of what comes back. Converting metres to a longitude delta divides by cos(latitude), which inflates the box toward the poles.
- Give two designs that work. In PostgreSQL: a geography column with a GiST index and ST_DWithin(pos, point, 3000), which is index-assisted, plus ORDER BY pos <-> point LIMIT 10 for ordered nearest-neighbour. ST_Distance(...) < 3000 written as a predicate is not index-assisted and is the version written by accident. Outside PostgreSQL: bucket on cell_id in an in-memory store and read the block of cells covering the radius, which keeps the candidate set in the low thousands.
- Argue the storage split with the write rate rather than by preference: 100,000 providers heartbeating every 4 seconds is about 25,000 writes per second, which is presence traffic competing for the same WAL as bookings, for state that is worthless 30 seconds later. Redis matches the durability this data actually needs: GEOADD stores members in a sorted set scored by a 52-bit interleaved geohash, and GEOSEARCH ... BYRADIUS reads it. Expiry has to be built rather than assumed, because a sorted set has no per-member TTL — EXPIRE applies to the whole key, and per-field expiry exists only for hashes, via HEXPIRE from Redis 7.4. Have each heartbeat also ZADD presence:seen <epoch_seconds> <provider_id>, sweep with ZRANGEBYSCORE presence:seen -inf (now - 30) and ZREM those members from both keys in one pipeline, and re-check the stored heartbeat at offer time so a member that outlived a missed sweep is still discarded. Snapshot periodically for analytics.
- State what is given up. Great-circle distance is a lower bound on road distance, so a radius prefilter on it never drops a provider whose road distance is inside the radius — the shortlist is admissible. Ranking on it is not defensible: it ignores rivers, one-way systems and the direction of travel. Shortlist by distance, then rank the shortlist by a routing ETA, paying that call on 50 candidates rather than 120,000.
- Name the residual failure modes so the design is not oversold: cell bucketing misses a provider just across a boundary unless the neighbouring cells are queried, and a radius that returns nothing must widen rather than fail — with a bounded number of widenings, because a request that expires unmatched is a first-class outcome, not an error.
Worked solution 30 min
- Write the naive cost: 400 x 120,000 = 48M distance evaluations per cycle, 96M per second at a 500 ms cadence, before the sorts.
- Assume the market spans about 40 km by 40 km, giving a density of 120,000 / 1,600 = 75 providers per square kilometre.
- Size a geohash-6 cell: 360 / 2^15 degrees of longitude is about 1.22 km and 180 / 2^15 degrees of latitude is about 0.61 km, so a 3 km radius needs about 3 rings east-west and 5 rings north-south, a 7 x 11 block of 77 cells.
- Compute the candidate set: 77 cells x 0.744 square kilometres each is about 57 square kilometres, so about 4,300 candidates, against the exact circle's pi x 9 = 28.3 square kilometres and about 2,120 providers.
- Compare: 120,000 / 4,300 is roughly a 28x reduction in rows scanned, with about half the survivors inside the true radius and needing the exact distance filter.
- Redo step 1 with a fleet of 12,000 to see where the naive plan becomes acceptable.
Follow-up
- At what fleet size does the naive version start meeting the budget again — show the arithmetic rather than guessing.
- The 3 km radius returns zero idle providers at 03:00; what does the loop do next, and when does it stop trying?
- Two dispatch partitions read the same idle provider from the index within one cycle — which layer prevents the double assignment, and why not this one?
Fix the double-counted totals in a two-child-table join
booking has two children: booking_adjustment(adjustment_id, booking_id, kind, amount_cents) and ledger_entry(entry_id, booking_id, account_id, direction, amount_cents, effective_at). Finance runs one query that joins booking to both, groups by booking_id, and sums each. For a booking with 3 adjustments and 4 postings the adjustment total comes out four times too large. Explain the mechanism, then write a correct query returning one row per booking completed yesterday with its adjustments total and the net amount owed to that provider. Say when you would use LATERAL and when a pre-aggregated CTE.
Approach
- Name the mechanism: joining two independent one-to-many children produces their cross product per parent, so 3 adjustments and 4 postings yield 12 rows and each child's aggregate is multiplied by the other child's cardinality. The fingerprint is that the wrong total is an exact integer multiple of the right one, which is why it survives code review — it looks like a number, not like an error.
- Reject the plausible patch.
COUNT(DISTINCT entry_id)is correct because the id is unique, butSUM(DISTINCT amount_cents)collapses two genuinely distinct 500-cent adjustments into one and is wrong in a way that only shows up when amounts repeat. - Aggregate each child independently.
LEFT JOIN LATERAL (SELECT SUM(ba.amount_cents) AS adjustments_cents FROM booking_adjustment ba WHERE ba.booking_id = b.booking_id) a ON TRUE, and a second lateral for the ledger, is two index probes per booking and suits a small outer set such as one day. Pre-aggregated CTEs grouped bybooking_idscan each child once and hash-aggregate, which wins as the outer set grows; pick by outer cardinality and measure the crossover rather than asserting one. - Add the filter that is not optional and is easy to omit: every
transaction_idbalances, so summing all postings for a booking returns exactly zero. The provider figure must restrict to that provider'sprovider_payableaccount — resolved by joiningaccounton the booking'sprovider_id— and must sign by direction withSUM(CASE WHEN direction = 'credit' THEN amount_cents ELSE -amount_cents END). - Choose the date column deliberately.
booking.completed_atbounds which bookings appear, but a refund'seffective_atcan fall inside yesterday while itsposted_atis next week; state which column the report keys on, because re-running it tomorrow will return a different number under one choice and the same number under the other.
Worked solution 25 min
- Insert one booking with 3 adjustments and 4 postings, run the naive query, and confirm the multiples are exactly 4x and 3x.
- Rewrite with two lateral subqueries and re-run against the same data.
- Drop the
account_idfilter from the ledger subquery and observe what the net becomes. EXPLAIN (ANALYZE)both the lateral and the CTE form over a one-day window and over a 90-day window.
Follow-up
- Rewrite it with pre-aggregated CTEs and say at what outer cardinality you would switch, and how you would measure the crossover rather than guess it.
- How would you catch this class of bug automatically in a reporting test suite, given that the wrong answer is a plausible-looking number rather than an exception?
- The same booking has a refund with
effective_atin yesterday's window andposted_atnext week. Which does this report key on, and what does the other choice change?
Add a no-overlap reservation constraint to a live table
booking holds 400 million rows and takes roughly 1,200 writes per second. Rental and freelance bookings store start_at and end_at, and overlaps are currently prevented by an application-level select-then-insert that has produced 61 double bookings in six months. Add reserved_during TSTZRANGE and enforce non-overlap per listing_id across non-cancelled rows. Give the ordered migration, the exact statements, the lock each one takes, and say what you do about the step that has no concurrent path.
Approach
ALTER TABLE booking ADD COLUMN reserved_during tstzrange;— nullable with no default is catalog-only and does not rewrite the table, but it still takes ACCESS EXCLUSIVE briefly, and that request queues behind any open transaction while blocking every reader that arrives behind it. So each DDL statement runs withSET lock_timeout = '2s'and a retry loop. Reject the tidierGENERATED ALWAYS AS (tstzrange(start_at, end_at, '[)')) STOREDform: adding a stored generated column rewrites all 400 million rows under that lock.- Deploy dual-write before backfilling, not after. The application writes
reserved_duringalongsidestart_atandend_aton every insert and update; backfilling first leaves a growing gap of rows the backfill has already swept past. - Backfill by keyset pagination over the primary key in batches of a few thousand, one transaction per batch, pausing between batches:
UPDATE booking SET reserved_during = tstzrange(start_at, end_at, '[)') WHERE booking_id > $last AND booking_id <= $last + $n AND reserved_during IS NULL AND start_at IS NOT NULL;. Every touched row is rewritten, so this is 400 million dead tuples' worth of vacuum pressure and WAL; pace the batches against replication lag andn_dead_tuprather than running as fast as the database accepts. - Find the pre-existing violations before you attempt the constraint, because the 61 known double bookings will abort the DDL only after it has already built the entire index. Build
CREATE INDEX CONCURRENTLY booking_listing_range_idx ON booking USING gist (listing_id, reserved_during) WHERE status <> 'cancelled';(needsCREATE EXTENSION btree_gist), then self-join witha.listing_id = b.listing_id AND a.booking_id < b.booking_id AND a.reserved_during && b.reserved_duringand resolve each conflict as a product decision, not a data edit. - Confront the step with no concurrent path:
ALTER TABLE booking ADD CONSTRAINT booking_no_overlap EXCLUDE USING gist (listing_id WITH =, reserved_during WITH &&) WHERE (status <> 'cancelled');takes ACCESS EXCLUSIVE and builds its own index inline. There is noCREATE INDEX CONCURRENTLYequivalent,ADD CONSTRAINT ... USING INDEXaccepts only UNIQUE and PRIMARY KEY indexes, andNOT VALIDapplies to CHECK and foreign-key constraints, not to exclusion constraints. Either take a bounded window sized by a timed build on a sample, or get the invariant from aBEFORE INSERT OR UPDATEtrigger that first runsSELECT 1 FROM listing WHERE listing_id = NEW.listing_id FOR UPDATE, serialising writers per listing so the subsequent overlap check is safe. Say which you chose, and say that the trigger is the weaker of the two because it can be disabled and the constraint cannot. - Retire the old columns in a separate deploy: stop reading
start_atandend_atfirst, then drop them. Dropping them while any read path still uses them converts a reversible migration into an outage.
Follow-up
bookingis partitioned bymarket_id, and PostgreSQL does not allow an exclusion constraint on a partitioned table. What does a per-partition constraint actually guarantee here, and is it enough?- The backfill reaches row 180 million and replica lag hits 40 seconds. What do you change, and what do you deliberately leave alone?
- Half-open
[)or closed[]for the range: which did you choose, and what happens to a check-out at 11:00 followed by a check-in at 11:00 under each?
Design a real-time live commerce infrastructure supporting video strea…
Design a real-time live commerce infrastructure supporting video stream delivery, instant messaging, and synchronized real-time bidding.
Approach
- Choose a partition key and say what query it makes expensive.
- Fix the scope first: who calls this, how often, and what they do when it fails.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- How does this behave when that dependency is down for an hour?
- What breaks first when traffic grows ten times?
Implement a continuous memory block allocator class with methods for a…
Implement a continuous memory block allocator class with methods for allocating, tracking, and freeing continuous blocks.
Approach
- State the consistency you need, and where you are willing to be stale.
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
Follow-up
- How does this behave when that dependency is down for an hour?
- What would you drop to keep the system up under load?
Specify the idempotency contract for booking creation from a quote
POST /bookings binds a consumer to an existing quote: the body carries quote_id, request_id and a tokenised instrument. The server authorises against the payment gateway and inserts a booking row; booking has UNIQUE (request_id) and quote rows are immutable with an expiry. The caller is a mobile client with a 10 s timeout that retries twice. Specify the idempotency contract: where the key comes from, what is persisted and at what point, the response when the same key arrives with a different body, the response while the first call is still in flight, and the retention floor.
Approach
- Tie the key to the user's intent, not to the HTTP attempt: the client mints a UUID when the consumer taps confirm, stores it, and replays it on every retry of that tap. A key generated per request defeats the whole mechanism while leaving it visibly in place, which is the failure mode that survives code review.
- Persist the key before doing anything external. Insert an idempotency record with a UNIQUE constraint on the key and a status of in_progress, and commit that before calling the gateway - if it is written after the call, a crash in between leaves a charge with nothing pointing at it. Store a fingerprint alongside it: a hash over the canonicalised fields that must not change, here quote_id, request_id and the instrument token.
- Define the three arrival cases precisely. A new key runs the operation. A known key whose fingerprint matches and whose record is completed replays the stored status code and body byte-identically, including when that status was a 4xx. A known key whose fingerprint differs is refused with 422 and a distinct code, without executing - the client has reused a key for a different intent, and guessing which one it meant is how you double-book.
- Handle the in-flight case explicitly rather than by waiting: return 409 with Retry-After: 1 and a code the client can act on. A 202 invites the client to move on as though a booking exists, and blocking the second request until the first finishes just moves the timeout.
- Set retention from the client's behaviour, not from taste: the record must outlive the longest retry horizon the client can produce plus the gateway reconciliation lag for unknown outcomes, so 24 hours is a floor here, held in a TTL-partitioned table. Note the interaction with quote expiry: a replay must return the stored response and must not re-validate the quote, because the booking already exists and re-checking an expired quote would turn a successful retry into a spurious failure. UNIQUE (request_id) is the backstop for a client that loses its key entirely - map that violation to the existing booking's representation rather than a 500.
Worked solution 30 min
- Write the key provenance rule and the exact moment the client generates and discards a key.
- Implement the reservation insert with its UNIQUE constraint, committed before the gateway call, and the read-back path on conflict.
- Define the fingerprint over the canonicalised triple and the 422 refusal on mismatch.
- On completion, write the status code, response body and booking_id in the same transaction that flips the record to completed.
- Exercise three interleavings: a sequential retry after a timeout, two concurrent requests sharing a key, and a replay issued after the quote has expired.
Follow-up
- The gateway call times out and the record stays in_progress forever because the process died. What sweeps it, and what does the endpoint return in the meantime?
- The consumer taps confirm twice deliberately, wanting two bookings. How does the contract tell that apart from a retry?
- Where does the idempotency record live relative to the booking row, and what breaks if they are in different databases?
One booking partition stops consuming after an enum is added
Booking events are published from outbox_event onto a 32-partition log keyed by booking_id, consumed by a group of 32 members. After a release that added the 'disputed' status, notifications and captures stopped for about 3% of bookings while aggregate consumer lag looked normal. One pod restarts every few seconds. Give the ordered checklist, what you do with the offending record, and what you must not do to the bookings whose events were sitting behind it.
Approach
- Start with per-partition lag, not aggregate lag. An average over 32 partitions hides one partition climbing while 31 sit at zero, which is exactly the shape that produces a small, stable percentage of affected bookings. Then take the restarting pod's exception and the record coordinates it names -- partition, offset, key -- and then the committed offset for that partition, which will be identical across every restart.
- State the mechanism plainly: a consumer cannot commit past a record it cannot process, so one bad record blocks every later record in that partition. Because the key is booking_id, the affected population is every booking hashing to that partition, roughly one thirty-second of traffic, which is where the 3% comes from. The restart loop also reprocesses everything after the last committed offset, so any side effect already issued before the crash is repeated -- which is why the consumer's idempotency matters before you touch anything.
- Verify the cause instead of assuming it: the deserializer rejects an enum value the deployed consumer does not know. Distinguish an unprocessable record from a transient downstream failure before doing anything destructive, because a blanket rule of dead-lettering on any exception silently discards real work during a dependency outage -- the same symptom with the opposite correct response.
- Handle the record: bounded retries with backoff, then copy it to a dead-letter destination carrying partition, offset, key and the exception, commit past it, and alert. Never reset the offset to the latest position to unstick the partition, which discards every record between the poison one and the new position, and never delete it, because it is the only copy of a transition that did happen.
- Repair what was stuck behind it rather than declaring the incident over when lag drops. Replay from the dead-letter destination once the consumer understands the value, relying on the outbox's unique (aggregate_type, aggregate_id, sequence_no) to reject duplicates and to expose gaps. Skipping broke per-booking ordering for that one booking, so every replayed event must be applied as a guarded transition against expected state, never as a blind status write.
- Close the class rather than the instance: consumers ignore unknown enum values instead of failing on them, and the consumer that understands a new value ships before any producer writes it. Note that adding members to the group cannot help, since a partition is assigned to exactly one member and members beyond the partition count sit idle.
Follow-up
- A capture was issued for a booking just before the crash and the restart reprocesses that record. What prevents a second charge, and where is that guarantee enforced?
- How would you alert on this specific shape -- one partition stalled -- without paging on ordinary lag?
- The dead-letter destination now holds 900 records across 60 bookings. In what order do you replay them, and why does the order matter for some and not others?
Roughly ninety minutes on weeknights with one longer weekend block. The plan cuts scope rather than compressing everything, on the assumption that one thing finished per night beats four half-started.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Screening call and a cold baseline
- Mark each line of the posting as done, adjacent or new, and write down which reported team (core search, seller tools, payments, advertising, eBay Live) and stack the seat most likely belongs to
- Write short answers to why this company, why you are leaving your current role, and one backend service you built and what you learned from it
- Solve one reported coding question cold (longest substring without repeating characters) and write one sentence on what slowed you down
- List the questions for the recruiter: first-stage and next-stage format, allowed languages, and the coding environment
Deliverable: A one-page screening sheet with the posting mapped, three short answers, recruiter questions and one cold-attempt note.
Practice prompt ↗Practice prompt ↗Worked solution ↗02Arrays, strings and hashing
- Solve longest substring without repeats with a sliding window and last-seen indexes, stating O(n) time
- Solve top-K frequent elements three ways (sort, size-k min-heap, frequency buckets) and state the complexity of each
- Restore an array from unordered adjacent pairs: build an adjacency map, start from an element that appears in only one pair, and walk
- For each solution, write tests for empty input, a single element, duplicates and ties before calling it done
Deliverable: Three working solutions with complexity notes and a boundary-case test list for each.
Practice prompt ↗Practice prompt ↗03Grids, graphs and cost reasoning
- Count connected regions in a grid with BFS or DFS, and write the version that marks cells visited without changing the input
- Search a row- and column-sorted matrix with the top-right staircase walk and explain why it is O(m + n)
- Find all reportees exactly N levels below an employee with a level-by-level BFS over the reporting map
- Work through the proximity-scan worked exercise (drill-coding-3) to practise putting numbers on why a correct but naive approach cannot ship
Deliverable: Three traversal solutions with tests, plus the proximity-scan arithmetic written out.
Practice prompt ↗Practice prompt ↗04Object-oriented and low-level design
- Implement an LRU cache with TTL expiry: O(1) get and put, lazy expiry on reads, and one reclaim strategy for entries that are never read
- Implement a contiguous block allocator with allocate, free and tracking, then test fragmentation, double free and a request larger than any free run
- Model an online chess game as classes and interfaces, and say where move validation and game state live
- Refactor a data-access class to use a connection pool and roll back on failure, and say what happens when the pool runs out of connections
Deliverable: Two tested implementations and one class diagram, each with a note on thread safety.
Practice prompt ↗Practice prompt ↗Worked solution ↗05System design with commerce-shaped prompts
- Design a flash-sale order pipeline: fix peak rate and stock first, then the inventory decrement, the queue that absorbs the spike, and idempotent order creation
- Design a live-commerce platform with video delivery, chat and synchronized bidding, and state the consistency the bid path needs compared with chat
- Work through the idempotency-contract worked exercise (drill-design-4) and the join fan-out SQL worked exercise (drill-sql-1) to cover retries and reporting correctness
- Write one paragraph each on Kafka-style asynchronous messaging, cache invalidation and race-condition prevention
Deliverable: Two designs at requirements, API and data-model depth, each with one trade-off you chose against and what would change your mind.
Practice prompt ↗Practice prompt ↗06Behavioral stories, four levels deep
- Pick four projects and write out what you did, why, why not the alternative, and what would have made the alternative win
- Map the reported prompts to your projects: a production outage you resolved, an architectural disagreement, pushing back on scope against technical debt, changing requirements, and tough feedback
- Have someone ask why three times in a row on each story and mark where your answers start repeating
Deliverable: A one-page index mapping each reported behavioral prompt to a project, with the weak points marked.
Practice prompt ↗Practice prompt ↗07Mixed rehearsal and taper
- Run one mock that covers a coding question, a low-level design question and a system design question back to back, and write down the three moments you lost the thread
- Fix only those three moments, and open no new material
- Confirm the logistics with your recruiter: the coding environment, the allowed languages, and whether the interviews are remote or on-site
Deliverable: A one-page card with your coding checklist, your design opening questions, your four project summaries and the confirmed logistics.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
The reported behavioral prompts for this role are about engineering work: incidents, disagreements, scope and changing requirements. The size of a project says little. What carries weight is the decision you owned, the evidence behind it and what happened afterwards. Prepare a few projects deeply enough to hold up through repeated follow-up questions.
How do you approach architectural disagreements or technical conflicts…
How do you approach architectural disagreements or technical conflicts within an engineering team?
Approach
- Close with what you would do differently, concretely.
- Give the blast radius: what could have broken, and what you measured.
- Pick a story where you made the decision, not one where you watched it.
Follow-up
- What would you do differently if you ran that again?
- What did you decide not to do, and why?
Describe a complex technical defect or production outage you diagnosed…
Describe a complex technical defect or production outage you diagnosed and resolved under pressure.
Approach
- Give the blast radius: what could have broken, and what you measured.
- State the situation in two sentences and spend the rest on the reasoning.
- Close with what you would do differently, concretely.
Follow-up
- How did you know your change caused the improvement?
- What did you decide not to do, and why?
Disclosing a money bug nobody has complained about yet
You discover that a retry path has been double-capturing: rows in payment_attempt with status 'unknown' were retried with a freshly generated idempotency_key instead of the stored one, so some bookings carry two successful captures. No customer has complained. You have the ledger and the gateway's own records. Describe what you do, in what order, and whom you tell. State what you stop first, how you bound the affected set exactly, how corrections reach ledger_entry, and what you say to your manager if asked to hold the disclosure until the quarter closes.
Approach
- Stop the bleeding before measuring it. Every hour spent investigating with the retry path live adds rows to the set you will later have to refund, so the first action is a flag, a config change, or a revert - whichever reaches production fastest.
- Bound the set exactly rather than estimating. Group successful captures by booking_id having count(*) > 1, then confirm each candidate against the gateway's record, since the local table is the artefact you already know to be wrong. Produce a list of booking ids and a total amount, not a rate.
- Escalate in writing, immediately, with the number attached and a next-update time. A money defect has owners outside engineering, and the cost of support or finance hearing it from a cardholder instead of from you is out of all proportion to the delay you saved.
- Remediate with postings, never edits: one compensating refund posting per duplicated capture, idempotent per booking and duplicate attempt, leaving the original rows untouched so every historical report stays reproducible. Confirm each transaction_id still sums to zero.
- Close the class rather than the instance. Derive the idempotency key from (booking_id, kind, logical_attempt) and persist it before the call so a retry replays it byte-identically; add the reconciliation pass that resolves 'unknown' against the gateway instead of guessing; add an alert that fires on any booking with more than one succeeded capture.
- On the request to wait: say that you will not delay notification, offer to sequence the remediation around the close, and put the disagreement in writing. The refusal is quiet and specific, not a stand on principle.
Follow-up
- The duplicate window overlaps a payout batch that already paid providers on the inflated amounts. What now?
- How do you choose between proactively refunding everyone affected and waiting for disputes to arrive?
- The gateway's record disagrees with your ledger for eleven bookings. Which one do you trust, and what do you do about the rest?
- 01
Describe a complex technical defect or production outage you diagnosed and resolved under pressure.
- 02
How do you approach architectural disagreements or technical conflicts within an engineering team?
- 03
Describe a situation where you had to push back on scope or balance product deadlines with technical debt remediation.
- 04
Walk through a project where you adapted to ambiguous or changing functional requirements mid-development.
- 05
Describe the services you built and the lessons you learned from running them.
- 06
Tell me about a time you received tough feedback and what you changed afterwards.
Is this an official eBay interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at eBay. The rounds and questions reflect what candidates have reported, not a process eBay has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗What stages do candidates report, and how long does the process take?
Candidates report three stages over roughly three to five weeks: an initial screening call, technical interviews covering coding and system design, and behavioral interviews. Confirm the exact sequence with your recruiter, including whether your first stage is a fit call, an online assessment or a live technical screen.
PracHub interview research ↗What kinds of coding questions are reported?
Reported data-structure questions include restoring an array from unordered adjacent pairs, top-K frequent elements, longest substring without repeating characters, searching a matrix whose rows and columns are sorted, and connected regions in a grid. Practise stating the brute force and its cost first, then the improved approach and its complexity, and test boundary cases before you say you are done.
PracHub Software Engineer practice ↗Should I prepare object-oriented and low-level design separately from system design?
Yes. It is a separate reported category: an LRU cache with TTL expiry, a domain model for online chess, finding reportees exactly N levels below an employee, a contiguous memory block allocator, and refactoring database access code to use connection pooling and safe transactions. Prepare these as working, tested code with clean state handling, which is different preparation from drawing a distributed architecture.
PracHub Software Engineer practice ↗How should I approach the system design prompts?
Reported prompts include an ATM backend, an order pipeline under flash-sale peaks, and a live-commerce platform with video, chat and synchronized bidding. Before drawing anything, fix the traffic scale, the read and write ratio and the availability needs. Then set component boundaries and address consistency, caching and scaling explicitly, saying what each choice costs. Be ready to discuss asynchronous messaging with Kafka or queues, cache invalidation and race-condition prevention.
PracHub interview research ↗Can I choose my programming language?
Candidates report that a preferred language such as Java, C++, Python or JavaScript is generally accepted for data-structure rounds. Ask your recruiter whether your team expects a specific language such as Java or C++, confirm the coding environment, and practise in that environment without your usual editor tooling.
PracHub interview research ↗Are the interviews remote or in-person?
It depends on location and team. Candidates report that many screens and full loops run over video with a shared coding tool, while some regional development centres hold on-site interviews. Ask your recruiter which applies to you.
PracHub Software Engineer practice ↗Sources & methodology 3 sources ↗
Official role evidence, timestamped platform data and clearly labeled preparation advice.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
platform · Accessed 2026-09-24 - 02PracHub Software Engineer practice ↗
Cross-company practice questions for this role.
platform · Accessed 2026-09-24 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
platform · Accessed 2026-09-24