Robinhood Software Engineer Interview Experience — System Design Round Ended Early, Rejected in 9 Minutes
Company: Robinhood
Role: Software Engineer
Round: Onsite
Seniority: General
Outcome: Rejected
Company: Robinhood
Role: Software Engineer
Round: Onsite
Seniority: General
Outcome: Rejected
A bit of background: I graduated in 2021 and did four years of C++ SDK dev, mixed in with about two years of building a Python test framework. My company started requiring three days a week back onsite, and the commute was wearing me out, so I started looking for something closer to home. Robinhood's infra work wasn't really a match for my background, but they gave me an interview anyway, and in Canada the offer was genuinely on the higher side.
First was the recruiter talk. They asked about my current title, then came back and said they could only offer IC4, not the Senior role the JD implied. I asked about the range — IC4 was 130k-147k CAD plus 37k RSU per year. Felt like decent money, worth going for.
Round one was a phone screen, live coding: topological sort on a graph with no cycles.
Round two was the VO (virtual onsite), three parts: project deep dive, system design, and live coding.
Round one, in detail: very simple. You're given an acyclic directed graph, one node is the entry point. You trigger the entry point once, its children get triggered once each and go on to trigger their own children — output the trigger count for every node. Python only.
Example: A->B, B->C, B->D, C->D, D->E, D->F, E->F. Output is A1 B1 C1 D2 E2 F4 — D gets triggered twice (once from B, once from C), E gets triggered twice by D, and F gets triggered twice by D and twice by E, for four total.
Brute-force DFS or BFS both solve it. To make it more efficient you need a topological sort, but I couldn't work out how to handle incoming-edge weights in reverse order when they're not fixed ahead of time. So I proposed BFS instead, without re-adding nodes, where each node's weight is the sum of its parents' weights. I walked through the runtime, and that was enough to pass. They scheduled the recruiter talk for the next day, and the VO after that. Since I'm only in the office three days a week it wasn't convenient right away, so the recruiter talk landed the following week and the VO the week after that.
Round two, the final round, was the VO.
Part one was the project deep dive. I'd been doing C++ software, so I went back and forth on what to present — SDK dev doesn't really give you much ownership, and my personal projects were all just fun lone-wolf stuff (writing an RTOS, writing an online gambling bot, that kind of thing). I ended up going with an AI enhancement I built for my company's test framework: a Llama 3.1 8B model that automatically parses test logs, files tickets to the right teams, auto-rejects QA tickets that are missing information or have config errors, and assigns the remaining valid tickets to the rest of my team. Most of the design was mine, with some coordination with other teams, some work handed to interns, some collaboration within my own team. I talked through the technical side for about 40 minutes and the interviewer barely interrupted — just a few questions here and there, like how I made sure the AI's output was accurate, why I used a local model instead of a hosted one (the company didn't allow hosted models at the time anyway, and the local model was both faster and not any worse), how I filtered out log noise that wasn't a real error, and how I found time to work on an unfunded side project. It was mostly me talking. Then another ten-plus minutes on what I'd do differently if I redid it (I said maybe turn the whole thing into a fully automated team-knowledge base rather than something semi-manual) and where I thought it would go next (get leadership to sign off on deploying it to Jira and rolling it out to other teams).
Part two was system design — first time in my life doing one. The question was the job scheduler one: support creating a job that runs on a schedule, reliably run each task at its designated time, handle the case where a job doesn't finish on time, and support querying past job status and past job logs. I failed this round, probably because I just don't have backend or distributed systems experience. I opened by saying the core should be a scheduler that's idle most of the time — "reliably run each task at the designated time" made me think of a realtime-system scheduler, woken by a hardware timer interrupt. The interviewer cut in: "Let's focus on a distributed microservice structure — each of these components is a microservice on some cloud server. Start from the data flow from the moment a user creates a job."
I said okay — when creating a job, the user provides a schedule to run it on, a description of what machine and config to run it on, the program or script to run, a timeout limit, and a timeout handler — maybe these get sent to the scheduler over TCP. The interviewer cut in again and asked if I knew REST APIs. I asked if HTTP POST and GET counted, and he said yes. So I kept going: the client POSTs this to the scheduler, the scheduler stores it in an array, and when it's time it allocates resources, sends the program over to run, and waits for a response and logs — maybe over a long-lived TCP connection. The interviewer cut in again: what kind of database would you use? I blanked for a second — oh right, there's also the database to think about — then said it should probably be a relational database with job id as the unique key, though logs probably don't need one; I'd just store those as files named by job id, run number, and date-time.
Anyway, it was enough of a mess that the interviewer wrapped the interview up early.
Part three was live coding, the next day, Python only. It seemed to mostly be testing OOP and design: build a payment system given a list of requests split into register user, send friend request, accept friend request, and transfer money. Only friends can transfer money to each other, and a transfer can't exceed the sender's balance. There was a small trap in the friend-request part — a request looks like "req_id/friend_req/user1/user2", but accepting one looks like "req_id/friend_accept/req_id", meaning you have to store the original request by its req_id and then, on accept, look it back up to find user1 and user2 and register them as friends. I kept forgetting that while coding and the interviewer had to remind me twice. Roughly, my design had a User class with a balance, id, friend list, and methods to check if two users are friends, check balance, and add money; a FriendRegistration class that stores all the friend requests and can register two people as friends given a user list; and a main function that parses requests, handles transfers, and stores all the users. Since I was rushing to finish, a few things I only left as comments instead of actually writing — like the fact that add_money should really only be callable by the transfer system itself, not something anyone can call to add money to a user. If this had been C++ I would have pulled the command parsing and payment logic out of main into a Payment class, declared add_balance() as a friend method, or just made FriendRegistration and User subclasses of Payment so nothing else could touch them directly. Also flagged that transfers shouldn't allow negative amounts, and that the balance updates need to be atomic under multithreading.
Then Q&A, and that was it.
After the live coding round, the recruiter emailed asking how it went, and I got the rejection nine minutes later. No feedback.