Box Senior Software Engineer Interview Experience — Aced Five Rounds, Failed on the Resume Deep-Dive
Company: Box
Role: Software Engineer
Round: Onsite
Seniority: Senior+
Outcome: Rejected
Company: Box
Role: Software Engineer
Round: Onsite
Seniority: Senior+
Outcome: Rejected
A recruiter reached out to me about a Senior SDE position — half development, half DevOps. I didn't have DevOps experience, but I said yes anyway.
Round 1 was the technical phone screen, the classic four questions. The interviewer laughed and admitted the questions hadn't changed in years.
A system has failed and you can only SSH in to check the logs. The log file is huge — what do you do?
Answer: grep is enough. I added a bit more — if this is a recurring issue, you could export the logs to ElasticSearch and save a query script in Kibana so it's easy to check next time.
Flip a bit at a given position.
num ^ (1 << position)
Given some concurrency code that uses locks, what's wrong with it?
There's a deadlock, and I fixed it.
Given a file path that contains subpaths or files, count word frequency across all the files under that path and return the top K.
Recursively read all the files, count the occurrences of each word and store them, then use a min-heap to output the top K.
The follow-up was: what if there are too many files to fit in memory? There are two approaches:
One is MapReduce — bucket the counts, write them to disk, then merge. The trade-off is a lot of disk I/O, which is slow.
The other is stream processing using Count-Min Sketch + Space-Saving, which is very efficient. The trade-off is it isn't 100% precise.
Round 2 was a 1-hour conversation with the hiring manager. It wasn't behavioral and it wasn't system design — I was given a whiteboard and asked to draw the architecture of a system I'd built, explaining as I drew.
Round 3 was 1 hour of coding: implement a rate limiter using the leaky bucket strategy, then write my own test cases and run them. After that we discussed concurrency scenarios and how to improve it in a distributed environment.
Round 4 was a 1-hour technical deep dive. The technical lead read through my resume and dug deep into my work experience as we went — how I did this, how I thought of that, why I used this instead of something else. It was all just talking, no coding, but the questioning went very deep, and there were a few times I couldn't answer. Afterward the recruiter told me I'd done perfectly in every other round — this was the one I failed.
Round 5 was 2 hours of coding. It turned out not to be the in-memory DB question people on the forum usually mention, but a new question. The interviewer handed it to me and then left; I spent about 50 minutes writing the solution and testing it against all the cases, then sat waiting for another 40 minutes for the interviewer to come back and review it.
The problem: given an infinite stream of events, each event has an id, a timestamp, a payload string, and a checksum. The checksum is used for validation. Events don't necessarily arrive in timestamp order — a later arrival could have an earlier timestamp than one already seen. If an event arrives too late, outside the time window, discard it. Design an event processor that computes the average payload string length within a given 1-minute time window. The overall time complexity has to be O(n log n), where n is the total number of events.
from heapq import heappush, heappop
class Event:
def __init__(self, id: int, timestamp: int, payload: str, checksum: int):
self.id = id
self.timestamp = timestamp
self.payload = payload
self.checksum = checksum
def validate(self) -> bool:
total = 0
for c in self.payload:
total += ord(c)
return self.checksum == total % 10
class EventProcessor:
"""
Processes a possibly out-of-order infinite event stream and computes
the average string length within a 1-minute sliding window.
"""
def __init__(self, window_seconds=60):
self.window_seconds = window_seconds
# Min-heap storing (timestamp, payload_length)
# Python's heapq is a min-heap, well suited to ordering by timestamp
self.heap = []
# The latest timestamp seen so far
self.max_timestamp_seen = -float('inf')
# Running total length and event count within the window, for O(1) average
self.total_length = 0
self.event_count = 0
def process_event(self, event: Event):
if not event.validate():
print(f"Event {event.id}: Invalid checksum")
return
# 1. Update the latest timestamp seen
self.max_timestamp_seen = max(self.max_timestamp_seen, event.timestamp)
# 2. Define the boundary of the current time window
window_start = self.max_timestamp_seen - self.window_seconds
if event.timestamp < window_start:
print(f"Event {event.id}: Ignored. too late received")
return
# 3. Compute the length of the new event's string
current_length = len(event.payload)
# 4. Push the new event onto the heap and update the running stats
heappush(self.heap, (event.timestamp, current_length))
self.total_length += current_length
self.event_count += 1
# 5. Pop all expired events off the top of the heap (timestamp before the window start)
# The heap top is always the event with the smallest timestamp
while self.heap and self.heap[0][0] < window_start:
# heappop removes and returns the smallest item
old_timestamp, old_length = heappop(self.heap)
# Update the running stats
self.total_length -= old_length
self.event_count -= 1
# 6. Compute and report the average
average = 0
if self.event_count > 0:
average = round(self.total_length / self.event_count, 2)
print(f"Event {event.id}: average {average} window end {self.max_timestamp_seen}")
Round 6 was a half-hour behavioral interview. The interviewer was friendly, and the questions were all the usual ones.