Software Engineers at Reddit work on the systems behind the content feed, real-time chat, search and ads, and on machine learning pipelines. The source notes name team areas such as Core App, Ads Engineering, Infrastructure and Community Tools. Depending on the seat, the day-to-day work is building microservices, optimizing data pipelines, or working on web and mobile clients. The notes also list architectural design reviews, code reviews and on-call rotations as part of the job, so be ready to talk about operating a system as well as shipping features.
The reported questions reflect that spread. The coding questions include classical algorithm problems: finding nodes with zero or one parent in a parent-child graph, the lowest common ancestor of two nodes in a binary tree, BFS or DFS over arrays, and processing a transaction stream with hashing. They also include practical domain problems: a tennis scoring tracker with deuce and advantage, parsing an administrator action log and checking whether one admin can remove another, merging fragmented chat messages, and an in-memory cache with eviction. The reported design questions cover a newsfeed that distributes posts to subscriber feeds, an ad-serving API with real-time click and impression aggregation, a caching layer for a read-heavy application, and an ML feature store or real-time signal pipeline.
The role notes list Python, Go, Java, C++, TypeScript and Swift or Kotlin as languages, and PostgreSQL, Redis and Cassandra as data stores. They list AdTech, auction systems and streaming systems such as Kafka as nice-to-haves. Use that list to choose your design vocabulary, but only claim tools you have actually run in production.
The practical coding category is where a purely puzzle-based preparation falls short. Practise modelling state and parsing input cleanly. Build a working baseline before handling every edge case, and say your assumptions out loud whenever a prompt leaves the input format open.
Recruiter Conversation
reportedCandidate reports describe this as a conversation with a recruiter about your background, your career direction and how you fit the open positions. Use it to find out which seat you are interviewing for. The role notes name team areas such as Core App, Ads Engineering, Infrastructure and Community Tools, and the work ranges from backend services and data pipelines to web and mobile clients. Also ask which format the technical screen takes, because reports describe both a live coding session and a hiring manager phone screen. Say which parts of the posting you have done and which you have not. If you claim all of it, the gaps come out in a later round.
What to demonstrate
- Whether your background maps clearly onto one team area and one kind of work rather than onto the whole posting
- Whether you can explain your career direction, and why this role fits it, in a few concrete sentences
- Whether you are open about the parts of the posting you have not done
How to prepare
- Mark each line of the posting as done, adjacent or new, and for each adjacent line write one sentence naming the closest thing you built
- Ask which team the role is on, whether the technical screen is live coding or a hiring manager screen, and how the onsite sessions are split
- Prepare a short answer to why you want to join Reddit that names a community you actually use and one concrete thing you noticed about it
Technical Screening
reportedReports describe this stage as either live coding in a collaborative editor such as CodeSignal or CoderPad, or a hiring manager phone screen. Either way it focuses on core algorithms, coding fluency and problem-solving speed. Candidate notes say screens often use classical problems on arrays, trees and graph search. The reported coding questions include finding nodes with zero or one parent in a parent-child graph, the lowest common ancestor in a binary tree, BFS or DFS over arrays, and a transaction stream solved with hashing. Write a correct brute force first and state its cost. Then improve it while the working version is still on screen. Before you say you are finished, trace an empty input, a single element and duplicate keys.
What to demonstrate
- Whether degenerate inputs get checked without prompting: an empty collection, one element, all elements equal, and a node that appears only on one side of a relationship
- Whether the complexity you state matches the code you actually wrote, including a sort or a copy inside a loop
- Whether you check the finished answer against the worked examples before calling it done
How to prepare
- Drill the reported coding categories: a parent-count map built from edge pairs, lowest common ancestor in a general binary tree and in a BST, BFS or DFS on a grid, and a single hash-map pass over a stream
- Practise the brute force as a separate skill: on ten problems, write only the obviously correct slow version and time how long it takes to pass
- Take five problems you have solved and, without running anything, write what each returns for empty input, one element and all duplicates; then run them and count how many you got wrong
- If you get a hiring manager screen, prepare a walkthrough of one system you built: its scale, the part you owned, and one trade-off you made
Virtual Onsite Loop
reportedReports describe a virtual onsite that can include multiple sessions and can be split across two days. It covers practical domain coding, system design, product and cross-functional collaboration, and behavioural conversations. Candidate notes say onsite coding leans on practical object-oriented modelling, string processing and domain design more than on puzzle-style algorithms. The reported questions in those categories include a tennis scoring tracker, an admin log parser with a seniority-based permission check, and chat message merging with caching. The reported design questions include a newsfeed, an ad-serving API and a caching layer. For the practical problems, build a working baseline and then extend it. Aim to leave each session with one concrete thing the interviewer can cite, such as a bug you caught yourself or a trade-off you named. Keep your project facts the same in every session.
What to demonstrate
- Whether practical coding problems get clear state and classes, and whether you extend them in steps without breaking what already worked
- Whether a design states requirements, a data model and the scaling bottleneck before choosing components
- Whether the scale, team size and decisions you attach to a project stay the same when it comes up in a different session
- Whether you describe work with product managers and data scientists in terms of a specific decision and what it cost
How to prepare
- Build the tennis tracker and the admin log parser in stages: get one game or one record type tested first, then extend it
- Sketch the newsfeed with push, pull or hybrid fanout and the ad aggregation path with idempotent counting, then work the at-most-once push design exercise
- Write a one-page sheet per project with the figures you will quote, and repeat them aloud until they come out the same every time
- Prepare one cross-functional story: a decision you negotiated with a product manager or data scientist, what you gave up, and the result
8 candidate reports. Individual accounts describe a particular role and hiring cycle.
Reddit Software Engineer Interview Experience — A Word-Search Rule Clarified Too Late
The author reports an unsuccessful Reddit coding screen involving word search. After presenting the task, the interviewer remained quiet while the applicant worked. The author did not confirm the movement rules and implemented a more permissive search than the interviewer expected. A typo also consumed about ten minutes. Although the applicant’s own tests passed, the interviewer said near the end…
Read full experienceReddit Machine Learning Engineer Interview Experience — General Pooling and a Ranking Interview
I applied to a particular team while sending out lots of applications online. The first phone screen was a question from the forum: analyze a spent-hours dataset and predict clicks. Since I had prepared it, the interview went quite smoothly. A week after the interview, I still hadn't heard anything, so I logged into the candidate portal. The position I had applied for was gone, and the interview…
Read full experienceReddit Machine Learning Engineer interview experience: two DSA rounds
The interview was straightforward: two data-structures-and-algorithms rounds along with machine-learning knowledge. The interviewers were kind and easygoing, and one of them in particular made the conversation feel comfortable. The format matched what I expected for the role. There were no strange surprises, just a clean sequence with a relaxed tone. I did not receive an offer, but the interview…
Read full experienceReddit Backend Engineer Interview Experience — Load Balancer Deep-Dive and a One-Week Offer
General coding 1: the Report Chain problem General coding 2: the Tennis Game problem — afterward the interviewer also chatted with me a bit about the strategy pattern Backend programming: the Load Balancer problem: It's split into four parts, and they give you a codebase. Part 1: The load balancer keeps getting error code 500. You need to find the cause — the cause is that the LB has the hostname…
Read full experienceReddit Machine Learning Engineer Interview Experience — Tennis Scoring OOD With Sets and Side Switching
View report detailsPracHub editorial advice for the preparation topics above.
Counting only nodes that appear as children in the parent-child graph question
Build the parent count from every pair, and give every node that appears anywhere a count of zero first, including nodes that only ever appear as a parent. Nodes that appear only as parents are exactly the zero-parent answer, and a dictionary that records only children silently drops them. Ask whether duplicate pairs can occur. Before you finish, trace a node with two parents and a repeated pair.
Writing the tennis scoring tracker as one growing chain of if-statements
Name the states before writing code: point scores within a game, deuce, advantage, game won, and then set and match counters. Write the transition for a won point from each state, including advantage back to deuce, and reject points recorded after the match is decided. Get one game correct and tested before adding sets and the match. Extending a working game is cheaper than debugging a whole match of nested conditions.
Parsing the admin log before settling its format and what seniority means
The reported prompt asks for admins ordered by last addition time and a check of whether one admin can remove another based on seniority. Before parsing, state the record separator and timestamp format, and say what happens when an admin is added twice or removed and re-added. Also settle whether seniority means an earlier addition or a position in an ancestor chain (the related bank question uses ancestor relationships and creation timestamps). Write those assumptions down, parse into a map keyed by admin, and test the re-added case.
Aggregating ad clicks and impressions from an at-least-once stream with no event id
In the ad-serving and ad event pipeline design questions, the aggregates feed reporting and billing, so an event counted twice after redelivery is a billing error. Give each event a unique id and make the aggregation step idempotent, either by deduplicating on event id within the redelivery window or by upserting keyed rows. State that a partitioned log guarantees order only within a partition. Explain how late events are handled and how a batch reconciliation corrects the real-time count.
Answering 'why Reddit' and 'how would your manager rate you' with generic lines
The reported behavioural questions include why you want to join Reddit and which community is your favourite, and how your current or previous manager would rate you from 1 to 10. Use the product before the loop and name a community you actually read, with one concrete observation about how it works for its members. For the rating, give a number below 10, cite the feedback it is based on, and name the growth area and what you have done about it. A perfect score with no evidence leaves the interviewer nothing to write down.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Implement a solution to find nodes with 0 parents and 1 parent in a pa…
Implement a solution to find nodes with 0 parents and 1 parent in a parent-child graph relationship.
Approach
- State the target complexity and say which constraint rules the naive version out.
- Choose the data structure from the access pattern, not from familiarity.
- Walk one small example through your approach before writing the whole thing.
Follow-up
- Which test case would catch an off-by-one here?
- What is the worst case, and how likely is it on real data?
Process a transaction stream using optimal hashing and array lookup te…
Process a transaction stream using optimal hashing and array lookup techniques.
Approach
- 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.
- Name the brute-force solution and its complexity before improving on it.
Follow-up
- How does this change if the input no longer fits in memory?
- Which test case would catch an off-by-one here?
Solve array-based data manipulation problems utilizing depth-first sea…
Solve array-based data manipulation problems utilizing depth-first search (DFS) or breadth-first search (BFS).
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.
- Walk one small example through your approach before writing the whole thing.
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 binary tree structure, find the lowest common ancestor of two …
Given a binary tree structure, find the lowest common ancestor of two specified nodes.
Approach
- Choose the data structure from the access pattern, not from familiarity.
- Restate the input: its shape, its size, and what is guaranteed about it.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Suppress duplicate notifications under bounded memory and redelivery
The notification path receives envelopes as (recipient_id, dedup_key, ts_ms) at 300,000 per second, and at-least-once redelivery means the same (recipient_id, dedup_key) can reappear at any point within 24 hours. Deliver each pair at most once per 24-hour window using memory that does not grow with the stream. Exact deduplication over 24 hours at this rate spans roughly 26 billion events, which does not fit in memory. Give the design, state the memory it consumes, and state precisely which direction it can be wrong in and how often.
Approach
- Separate events from distinct pairs before sizing anything. The gate only has to remember distinct pairs, not deliveries, so measure the redelivery ratio first: at 26 billion events and a 12x ratio the distinct set is about 2 billion, which at 16 to 24 bytes an entry is still 32 to 48 GB. That does not by itself solve the problem, but it changes the constant by an order of magnitude and it is the first number to establish.
- Make expiry O(1) per bucket rather than per entry by time-bucketing the state: 24 rotating hourly sets, a lookup probes all 24, an insert goes to the current one, and expiry frees the oldest set wholesale. Per-entry TTLs cost a delete per entry and fragment the allocator. Two prices come with that bucket count and both are quantitative: the effective window runs from 24 to 25 hours depending on where in a bucket the first delivery landed, and a lookup gets 24 independent chances to return a false positive rather than one. State the slop instead of claiming exactly 24 hours, and carry the 24 into the sizing rather than the footnotes.
- Choose the error direction deliberately, which is the real content of the question. A Bloom filter has no false negatives and false positives at rate p, so a false positive suppresses a real notification: a silent, user-visible loss with no recovery path. If the product prefers a rare duplicate to a rare silent drop, demote the filter to a negative cache where a miss is definitive and a hit is confirmed against a durable store, so a false positive costs one lookup instead of a notification.
- Size from the rate a caller sees, not the per-filter rate, or the headline is wrong by the bucket count. The 24 filters hold disjoint sets, so their false positives are independent and the delivered rate is P = 1 - (1 - p)^24, about 24p. Invert it: p = 1 - (1 - P)^(1/24), about P/24. For a target P = 10^-4 that is p = 4.2 * 10^-6, and the optimal geometry is bits per element = 1.44 * log2(1/p) = 25.8 with hashes = 0.693 times that, about 18 per filter, so 2 billion distinct pairs is roughly 6.4 GB across all buckets against 32 GB or more for exact. Sizing each bucket at p = 10^-4 instead looks cheaper at 19.2 bits and 4.8 GB, but its delivered rate is 2.4 * 10^-3.
- Treat the bucket count as the tuning knob it is, with no free corner: B buckets give window slop up to 24/B hours, bits per element proportional to log2(B/P), and B filters probed per lookup. B = 4 costs 22.1 bits and 5.5 GB but up to 6 hours of slop; B = 24 holds the slop under an hour and costs 25.8 bits and about 430 random bit probes per lookup, which at 300,000 lookups per second is roughly 130 million random memory reads per second and is the part that bites on real hardware, not the gigabytes.
- Convert P into a number a product owner can accept or reject, noting that only a first delivery can be wrongly suppressed: about 2 billion first-deliveries a day times P = 10^-4 is roughly 200,000 notifications silently suppressed per day, and at the mis-sized 4.8 GB geometry the same sentence reads about 4.8 million. That sentence is the deliverable; the byte count alone is not. Then shard on a hash of the pair so each worker owns a disjoint key space and needs no coordination, or shard on recipient_id if coalescing decisions for one recipient must be co-located, and state the restart behaviour plainly: losing a worker's in-memory sets produces duplicates, not drops, which is the safer direction, and persisting only the current bucket bounds how many. Exact at-most-once needs memory proportional to the distinct pairs in the window; any design using materially less trades one error direction for the other, and the answer is naming which.
Worked solution 40 min
- Compute the exact bill first: 300,000 per second times 86,400 seconds is 25.9 billion events; apply a measured redelivery ratio to get distinct pairs, then price an exact hash set at 16 to 24 bytes per entry and write that number down.
- Lay out 24 hourly buckets, define lookup as a probe of all 24 and expiry as dropping the oldest, and state both consequences of that bucket count: window slop of up to one bucket, and 24 independent false-positive chances per lookup.
- Fix the delivered target P, invert the union bound to p = 1 - (1 - P)^(1/24), then size each bucket with bits per element = 1.44 * log2(1/p) and hashes = 0.693 times that, and report both the total in gigabytes and the bit probes per lookup.
- Convert P into the daily count of silently suppressed notifications, counting first deliveries only, and decide explicitly whether that is acceptable; if it is not, restructure the filter as a negative cache in front of a durable store.
- Choose the shard key, and state that a worker restart yields duplicates rather than drops.
Follow-up
- Add coalescing: 40 likes on one item within five minutes should become one notification. Does that change the key, the structure, or both?
- You are told a silent drop is unacceptable but a duplicate push is merely bad. Redesign the gate and state the new memory bill.
- The service does a rolling restart every 30 minutes. What does that do to your guarantee, and what is the cheapest durable state that restores it?
Take a viral item's like counter off one hot row
One item is taking 8,000 likes a second and the counter is a single row: UPDATE content_counter SET like_count = like_count + 1 WHERE content_id = $1. Describe precisely what that statement does under READ COMMITTED and under REPEATABLE READ, including whether a count is ever lost. Then give the sharded schema, the read query, the rule for choosing a shard, and the reconciliation job that rebuilds the number from engagement. State what is approximate, by how much, and for how long.
Approach
- Under READ COMMITTED that statement does not lose an update. A blocked writer waits on the row lock, then re-reads the newly committed version and re-evaluates like_count + 1 against it. The failure is throughput: every writer serialises behind one row lock, so the ceiling is roughly one increment per lock hold, and the hold spans commit and anything else still inside the transaction.
- Under REPEATABLE READ the same statement raises could not serialize access due to concurrent update (SQLSTATE 40001) rather than waiting the conflict out, so the hottest item produces the retry storm. The anomaly moved; it did not disappear, and prescribing stricter isolation here makes the incident worse.
- Distinguish the genuine lost update: SELECT the value, add one in application code, UPDATE with a literal. Under READ COMMITTED both sessions read 500 and both write 501, and one increment is gone with no error anywhere. Being able to tell this interleaving apart from the first one is the substance of the question.
- Shard: content_counter_shard(content_id BIGINT, shard_no SMALLINT, delta BIGINT NOT NULL DEFAULT 0, PRIMARY KEY (content_id, shard_no)). Pick the shard by hashing actor_id modulo N so a redelivered apply lands on the same row and any dedup stays local. Read is SELECT sum(delta) FROM content_counter_shard WHERE content_id = $1, one index range scan of N rows - the trade is read cost for write concurrency, so shard only above a popularity threshold and leave cold items on one row, which means the reader must know which mode an item is in, the same shape as the push/pull threshold.
- Reconcile from the ledger: SELECT content_id, count(*) FROM engagement WHERE action_kind = 'like' AND undone_at_utc IS NULL AND content_id BETWEEN $lo AND $hi GROUP BY content_id, batched by id range and compared against the shard sum. This only works because undo is recorded in place instead of deleted, and it is why the denormalised count is never the input to an authorization test.
- State the contract out loud: the number is approximate between runs, the drift is bounded by the deltas not yet reconciled, the displayed value can be stale by one reconciliation period, and nothing that must be exact - payouts, quotas, rate limits - reads it.
Worked solution 35 min
- Drive 32 concurrent sessions incrementing one row, recording transactions per second and lock waits from pg_stat_activity.
- Repeat under REPEATABLE READ and count the 40001 errors.
- Repeat with the application-side SELECT-then-UPDATE variant and compare the final value against the number of committed transactions.
- Create 16 shards, re-run the load, and compare throughput.
- Run the reconciliation query over the item and diff it against the shard sum.
Follow-up
- Two follows commit concurrently while follower_count is 9,999 and the push/pull threshold is 10,000. Each transaction reads 9,999 and neither flips fanout_mode. Name the anomaly, say which isolation level prevents it, and say what the database does when it detects it.
- How do you choose N, and what measurement tells you it is too high?
- Would you move the increment to an in-memory counter instead? State the loss window you are accepting and what makes it acceptable.
Reconstruct an item's like curve from an undo-in-place table
engagement records one row per (actor_id, content_id, action_kind) with created_at_utc and undone_at_utc, where an unlike sets undone_at_utc in place rather than inserting a second row. For one content_id, return the net live like count over time and the earliest instant it reached 500. Write the query. The obvious one-pass window over created_at_utc produces a curve that never dips - explain why that is wrong, state which window frame you rely on and why, and name the index each leg of your query needs.
Approach
- Say what the table is: current state, not an event log. SUM(CASE WHEN undone_at_utc IS NULL THEN 1 ELSE 0 END) OVER (ORDER BY created_at_utc) counts, at each past instant, the likes placed by then that are still live today, so every undo is applied retroactively to a moment before it happened and an item that reached 800 and fell to 300 never appears to have crossed 500.
- Unpivot into events first: one +1 at created_at_utc for every like row, one -1 at undone_at_utc for the rows where it is not null, combined with UNION ALL. Order the window over that unioned instant rather than over created_at_utc, because an undo can fall between two later likes.
- Run the running total with an explicit frame and choose RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW deliberately: the question asks for the count at an instant, so every event sharing a timestamp must resolve to the same value. ROWS would expose intermediate values inside one instant and can report a crossing that existed only between two simultaneous events. ROWS is right for a per-row ledger, RANGE for a level at a time.
- Take the crossing as MIN(at) FILTER (WHERE net_likes >= 500) over the running result rather than with LAG, because the question is about a level and not a change, and LAG also misreads ties.
- Index each leg separately: (content_id, action_kind, created_at_utc) for the like leg, and a partial (content_id, action_kind, undone_at_utc) WHERE undone_at_utc IS NOT NULL for the undo leg, since undos are a minority and the partial index keeps that leg off the full like history.
- State the modelling limit precisely: because the row is updated in place, a like then unlike then re-like leaves one row with undone_at_utc NULL, so that actor's dip is unrecoverable. The curve is exact for actions that are currently undone and approximate otherwise; an exact curve needs an append-only engagement_event ledger, which is the real deliverable this question is circling.
Follow-up
- Give the DDL for that append-only ledger and say what it costs at this write rate, and what you would stop storing to pay for it.
- Now return the curve bucketed per minute for a chart. What changes about the frame and about the index?
- Answer the same question for 10,000 items at once without running the query 10,000 times.
Architect an ad-serving platform API capable of handling high concurre…
Architect an ad-serving platform API capable of handling high concurrent bid requests and real-time click/impression aggregation.
Approach
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- Name the failure you are designing for, then the recovery path.
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?
Design a high-throughput, low-latency newsfeed system capable of distr…
Design a high-throughput, low-latency newsfeed system capable of distributing posts across millions of active subscriber feeds.
Approach
- State the consistency you need, and where you are willing to be stale.
- Name the failure you are designing for, then the recovery path.
- Choose a partition key and say what query it makes expensive.
Follow-up
- What breaks first when traffic grows ten times?
- What would you drop to keep the system up under load?
Admin Log Processing: Parse a long string of administrator action logs…
Admin Log Processing: Parse a long string of administrator action logs to generate an ordered list of administrators by last addition time, and implement a permission check method determining if one administrator can remove another based on seniority.
Approach
- Work from the requirement backwards to the design.
- State your assumptions explicitly before working the problem.
- Say what you would check first and why it is the highest-information step.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
At-most-once push when the dedup store fails over
Notification envelopes are generated at 250,000 per second from likes, replies and mentions. Each carries a coalescing key and a dedup key, and delivery goes through a device push gateway that is itself at-least-once. A duplicate push is user-visible; a missing push for a direct reply is a product failure. Dedup keys currently live in an in-memory store that can lose a partition on failover. Specify the delivery path, then state what you do during a dedup-store failure, per notification class, and the bound you commit to for each: deliver and risk duplicates, or suppress and risk losses.
Approach
- Split the two keys, because they solve different problems and need different lifetimes. The coalescing key (recipient, target, kind) collapses many actors into one envelope inside a window and is what turns 250,000 envelopes per second into a much smaller push rate; the dedup key stops a redelivered fanout event from creating a second envelope and must outlive the consumer's retry horizon.
- Move the invariant off the cache: a unique constraint on (recipient_id, dedup_key) on the durable envelope row makes at-most-once a property of the write, demoting the in-memory store to a negative-lookup filter that only saves latency. With that in place a failover is a latency and capacity event rather than a correctness event, which is the strongest available answer and should be stated before any fallback policy.
- Where the durable write is not affordable at this rate, make the choice per class and say it in product terms. High-salience direct notifications (reply, mention, direct message) fail open: deliver, accept a rare duplicate, because a lost direct reply is the worse outcome. Low-salience aggregate notifications fail closed: suppress, because a repeated 'someone liked your post' is noise and the miss costs almost nothing.
- Close the end-to-end gap honestly. The gateway is at-least-once and a device can receive a retransmit after a lost acknowledgement, so server-side dedup alone cannot give at-most-once at the device. Attach a stable notification identifier or collapse key so the client suppresses the repeat; without that the guarantee as stated is untrue regardless of the server design.
- Add backpressure and publish the bounds: cap pushes per recipient per window, shed the lowest class first, and commit to numbers, for example p99 under ten seconds from action to push, and during a failover at most one duplicate per envelope for the failover window for fail-open classes and full suppression for fail-closed classes.
Worked solution 40 min
- Write the envelope schema with both keys and state the lifetime of each.
- Write the insert that enforces at-most-once durably, and show what the in-memory filter adds once that exists.
- Classify notification kinds into fail-open and fail-closed, with one sentence of product justification per class.
- Describe the client-side suppression that closes the gateway retransmit gap.
- State the delivery latency bound and the failover-window bound separately.
Follow-up
- An account with 60 million followers publishes. Do you create 60 million envelopes? If not, what does the follower see instead?
- How long do dedup keys live, what does that retention cost at 250,000 per second, and what expires them?
- Show the interleaving where two workers both pass the negative filter. Name the exact mechanism that stops the second write.
Feed page latency scales with page size after a card redesign
A feed page of 40 items takes 1.4 s at p99; a page of 10 takes 380 ms. Feed service request rate is flat, but reads against the content and account stores are up 40x since last week's release, which added author badges and a per-item saved state to each card. No entry appears in the slow query log. You have distributed traces, per-request span counts, and both stores' statement statistics. Give the ordered list of what you inspect, the defect, and the fix with its cost.
Approach
- Start from the ratio, not the slow query log. The log is empty because no individual statement is slow; the defect is the number of statements, which that log cannot show. Divide store reads per second by feed requests per second and you get lookups per request. A per-request count that rises with page size is a per-item pattern by definition, and that single number localises the fault before you read any code.
- Confirm linearity deliberately: latency at page size 10 versus 40 is 380 ms versus 1.4 s, close to a 4x ratio on a 4x page size, so the cost is per item rather than per request. A fixed per-request cost would have shown a much flatter curve.
- Read one trace and count spans by name. Expect roughly four lookups per card after the release — author record, saved state from engagement, the block check, and the media rendition — so 40 items issue about 160 round trips. At 6 ms each, issued sequentially, that is around 960 ms of pure round-trip time and accounts for the whole regression without any query being slow.
- Replace per-item lookups with one batched statement per entity type: collect the ids for the whole page first, then issue WHERE content_id = ANY($1) and WHERE account_id = ANY($1). Two preconditions to state out loud: the application must re-associate results by key rather than by array position, because the database returns rows in an unspecified order, and it must handle ids that return no row, because a deleted or suspended entity silently shrinks the result set. Four batched queries replace roughly 160, which is O(1) round trips per entity type instead of O(k).
- Add a request-scoped memo keyed by entity id on top of the batch. A page of 40 items usually contains far fewer distinct authors than items, so deduplicating ids before the batch cuts the author fetch further, and the memo prevents the ranking and rendering passes from re-fetching what hydration already loaded.
- Make the defect detectable next time: export lookups per feed request as a metric, and add a test that renders a fixed page and asserts the query count stays under a constant. A latency threshold will not catch this again, because the per-item pattern is cheap at the page sizes used in tests.
Follow-up
- The block check is per viewer, not per item. Where does it belong in the request, and what changes about its cost once you move it?
- One of the batched ids returns no row because the item was deleted between the timeline read and hydration. What does the page render, and what does the timeline store do about that slot?
- Ranking needs an engagement count per item. Do you batch that from the counter store or accept a stale value, and what is the staleness bound you commit to?
For a candidate senior enough that the loop turns on design and judgement rather than on whether the coding round gets finished. Five days build one system properly and then stress it; coding gets a single maintenance day, on the assumption that the risk at this level is an unexamined tradeoff rather than a missed algorithm.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Recruiter call and role mapping
- Mark each line of the posting as done, adjacent or new, and match your experience to one team area the source notes name: Core App, Ads Engineering, Infrastructure, Community Tools, or web and mobile client work.
- Write three questions for the recruiter: which team, which technical screen format (live coding in a tool such as CodeSignal or CoderPad, or a hiring manager screen), and how the onsite sessions are split.
- Write your why-Reddit answer around a community you actually use and one concrete thing you noticed about how it works.
Deliverable: A one-page role map, three recruiter questions, and a why-Reddit answer that names a real community.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗02Technical screen: trees and graphs
- Solve the reported parent-child graph question (nodes with zero parents and exactly one parent) with a count map. Trace it on a node that appears only as a parent and on a repeated pair.
- Solve lowest common ancestor twice: once for a general binary tree with a recursive search, and once for a BST using the ordering (the bank's Lowest Common Ancestor in BST). State the complexity of each.
- Solve two BFS or DFS problems of your choice over an array or grid, for example counting connected regions with BFS and a flood fill with DFS. Write the brute force first and time how long it takes to pass.
Deliverable: Five solved problems (parent count, LCA in a binary tree, LCA in a BST, and two BFS or DFS problems), each with its complexity stated and a written trace for empty, single-element and duplicate inputs.
Practice prompt ↗Practice prompt ↗03Coding: hashing, intervals and streams
- Solve the reported transaction-stream question with a hash map. State what the map is keyed by and how large it grows.
- Solve the bank's Merge Overlapping Chat Messages: sort by stream and start time, then merge overlapping or consecutive intervals in O(n log n). Test touching intervals, one message, and messages from different streams.
- Implement the bank's sliding-window rate limiter and say whether your version is exact per request or approximate.
- Work the duplicate-notification worked exercise (Suppress duplicate notifications under bounded memory and redelivery) and recompute its sizing figures yourself.
Deliverable: Three working implementations with tests (transaction stream, chat message merge, rate limiter), plus your own recomputed numbers for the dedup exercise.
Practice prompt ↗Practice prompt ↗04Onsite: practical object-oriented coding
- Build the tennis scoring tracker in stages: one game with deuce and advantage, tested; then sets and match; then rejecting input once the match is over.
- Solve the admin log question. Write down the log format assumptions, parse into a map, return admins by last addition time, then add the permission check (compare the bank's Permission Deletion Logic).
- Design an in-memory cache with a memory bound, an eviction policy and an invalidation rule, and say why that policy fits the access pattern.
- For extra repetitions, time yourself on the bank's Implement a Stateful Chatter Message Store or Design Add, Overwrite, Undo, and Redo for Billing State.
Deliverable: The tennis tracker and admin log solutions built in stages, each with its assumptions and test list written out, plus a written cache design.
Practice prompt ↗Practice prompt ↗Worked solution ↗05Onsite: system design for feed and ads
- Newsfeed: choose push, pull or hybrid fanout and state the follower threshold where you switch. Name the partition key and the query it makes expensive.
- Ad-serving API: separate the bid request path from the click and impression aggregation path. Design idempotent aggregation and a reconciliation job.
- Work the design exercise (At-most-once push when the dedup store fails over) and compare your fail-open and fail-closed classes with the worked answer.
- Sketch the bank's Rate Limiter for Multiple APIs with per-user quotas enforced across several nodes.
Deliverable: Two designs taken to API, data model and failure handling, each with the trade-off you chose against written beside it.
Practice prompt ↗Practice prompt ↗06Storage, caching and incidents
- Work the SQL exercise (Take a viral item's like counter off one hot row), then explain the difference between lock contention and a genuine lost update.
- Work the debugging drill (Feed page latency scales with page size) and write the ordered list of what you inspect before reading the approach.
- Design the reported caching layer for a read-heavy application: cache-aside or write-through, the staleness window, and how you prevent a stampede.
- Write short answers to the bank's Database Down Scenario, CSRF Mitigation and XSS Mitigation. If the team is ads- or ML-adjacent, also sketch the ML feature store question.
Deliverable: The hot-counter exercise completed, a written N+1 diagnosis, a caching design, and short incident and web-security answers.
Practice prompt ↗Practice prompt ↗07Behavioural stories and onsite consistency
- Write STAR stories for the reported behavioural questions about a difficult colleague and harsh technical feedback, and one for the bank's Your Strengths and Weaknesses.
- Prepare the manager-rating answer: a number, the feedback behind it, the growth area, and what you changed.
- Prepare one story each for the bank's Collaborate Across Product and Data Science and Manage Technical Debt Under Delivery Pressure.
- Write a one-page fact sheet per project. Have someone ask you the same project question twice, an hour apart, and compare the two answers for numbers that changed.
Deliverable: Five behavioural stories, a manager-rating answer, and a project fact sheet that held steady across two tellings.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
The reported behavioural questions cover conflict with a colleague, handling harsh technical feedback, how your manager would rate you, and why you want to join Reddit. Prepare each one as a specific story you owned: the situation in two sentences, what you did, what changed afterwards, and what you would do differently. Keep the figures and decisions in these stories the same as when the same projects come up in coding and design conversations.
Describe a situation where you had to work with a difficult colleague.…
Describe a situation where you had to work with a difficult colleague. How did you resolve the situation and maintain team momentum?
Approach
- Close with what you would do differently, concretely.
- State the situation in two sentences and spend the rest on the reasoning.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What did you decide not to do, and why?
- What would you do differently if you ran that again?
Tell me about a time you received harsh or critical technical feedback…
Tell me about a time you received harsh or critical technical feedback. How did you process it and what changes did you make?
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Close with what you would do differently, concretely.
Follow-up
- What would you do differently if you ran that again?
- What did you decide not to do, and why?
Unblock an engineer seeing duplicate items on page two
An engineer on your team reports that users see the same items twice when they load page two of the feed. Their query is ORDER BY sort_key DESC LIMIT 40 OFFSET 40, and their proposed fix is to dedupe by content_id in the client. They are blocked, frustrated, and have been on it a day. Unblock them without taking the keyboard: get them to a reproduction, explain why the duplicates appear, why client-side dedup is the wrong layer, and what you would have them build instead.
Approach
- Get them to a deterministic reproduction before explaining anything. Insert k items at the head between the two requests and watch exactly k already-seen items reappear on page two. A reproduction they ran themselves teaches the mechanism; an explanation teaches them that you were right.
- Describe the cause as counting rather than as a bug. OFFSET defines a window by counting from the start of a result set that is mutating at the head, so k insertions above the window push k rows down into page two. Then show the half they have not seen: deletions shift the other way and skip rows entirely, with no signal to the client that anything was missed.
- Use the skip case to show why client dedup is the wrong layer. It suppresses the visible repeat and can do nothing about the invisible omission, because nothing ever told the client an item existed. Add the performance argument second: the database still produces and discards OFFSET rows, so page n costs more than page one even when no duplicate appears.
- Hand over the replacement with its precondition attached, because the precondition is where this bug comes back. Seek on the previous page's last key: WHERE owner_id = :owner AND sort_key < :cursor ORDER BY sort_key DESC LIMIT 40, served by the index on (owner_id, sort_key DESC). The key must be unique within the owner, or the boundary row is either repeated or dropped, which is why the sort key is the time-sortable content id rather than a timestamp that collides at high insert rates.
- Leave them the work and the proof: they write the query, the test that inserts at the head between page requests, and the plan check confirming an index scan rather than a sort. Then ask them to explain the skip case back to you, which is the only cheap way to find out whether the mentoring landed.
Follow-up
- What must the cursor encode once a page merges pushed timeline entries with items pulled from above-threshold authors?
- The product wants a 'new items above' indicator. How do you show what arrived above the cursor without breaking the page sequence?
- What test would have caught this before release, and why did the existing tests pass?
- 01
Describe a situation where you had to work with a difficult colleague. How did you resolve the situation and maintain team momentum?
- 02
Tell me about a time you received harsh or critical technical feedback. How did you process it and what changes did you make?
- 03
How would your current or previous direct manager rate your engineering performance on a scale of 1 to 10, and why?
- 04
Why do you want to join Reddit, and what is your favorite community on the platform?
- 05
How do you collaborate with product managers and data scientists to align goals and manage trade-offs?
- 06
Tell me about a time you had to reduce technical debt while still delivering committed roadmap work.
Is this an official Reddit interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at Reddit. Rounds and questions reflect what candidates have reported, not a process Reddit has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗What does the Reddit Software Engineer technical screen look like?
Candidate reports describe it as either a live coding session in a collaborative editor such as CodeSignal or CoderPad, or a hiring manager phone screen. Both focus on core algorithms and coding fluency. Ask your recruiter which one you have. To cover both, do timed algorithm practice on arrays, trees and graph search, and prepare a short walkthrough of a system you built.
PracHub Software Engineer practice ↗Can I choose my programming language for the coding rounds?
Candidate reports say you can generally choose a standard modern language such as Python, Go, Java or JavaScript/TypeScript. Confirm with your recruiter. Practise in the language you will use, including its standard collections for maps, heaps and sorting, so you are not looking up syntax during the round.
PracHub interview research ↗How much algorithmic coding versus practical coding should I expect?
Both. Candidate notes say screens often use classical algorithm problems (arrays, trees, graph search), while onsite coding leans on practical object-oriented modelling, string processing and domain design. The reported questions include a tennis scoring tracker and an admin log parser. Split your practice between the two, and for practical problems, practise building a working baseline and then extending it.
PracHub interview research ↗Which system design topics should I prepare?
The reported design questions cover a newsfeed that distributes posts to subscriber feeds, an ad-serving API with real-time click and impression aggregation, a caching layer for a read-heavy application, and an ML feature store or real-time signal pipeline. The bank adds a real-time ad event pipeline, a rate limiter for multiple APIs, a game leaderboard and scaling a small forum app. Prepare fanout strategy, cache invalidation, idempotent stream aggregation and rate limiting.
PracHub Software Engineer practice ↗Do I need ads or machine learning experience?
The role notes list AdTech, auction systems and streaming systems such as Kafka as nice-to-have skills, not requirements. Several reported design questions touch ads and ML pipelines, so learn the basics of event aggregation and feature freshness even if your background is elsewhere. Be clear about what you have and have not built.
PracHub Software Engineer practice ↗How soon do candidates hear back after the onsite?
Reports vary. Candidate notes say most people hear back within three to five business days after the final loop, usually through a call with the recruiter. At the end of the onsite, ask your recruiter what timeline to expect.
PracHub interview research ↗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