Interview Stories
Eight stories, in situation → action → result form, each with the follow-up questions it invites and the answer you should already have ready. These are drawn from committed code, so every one survives a "walk me through it."
Eight stories, in situation → action → result form, each with the follow-up questions it invites and the answer you should already have ready. These are drawn from committed code, so every one survives a "walk me through it."
Situation. Users were seeing nameless cards in their discovery deck — real rows, no display name.
Action. Traced it back through the sorting hat to the ranking pipelines.
match_cards is partitioned by (service_region, geohash4). The pipelines
iterate a configured list of regions, and the region in the loop is the pool
being ranked — not necessarily the pool the user's card lives in. Because
Cassandra UPDATE is an upsert, writing with the loop's region did not fail
and did not update: it created a new partition, one per user per configured
region, holding only score columns. The sorting hat then indexed those into
real decks.
Result. Added a partition-lookup layer that resolves the user's true
partition before any write, so partition identity is never inferred from
iteration context. Fix and reasoning committed in user_partition.go.
Follow-ups to expect
Situation. A Redis Streams feed index was silently falling behind.
Action. A Redis consumer group moves a message to the consumer's
pending-entries list on delivery and removes it only on XACK. Both feed
consumers continue past a processing failure without acking — which is
correct, since acking work you failed to do destroys it. But nothing ever came
back for those entries. feed_index:writes had accumulated 952 pending
messages, the oldest long past useful.
Result. Implemented an aged-entry reclaim path so failed work is retried
rather than orphaned. stream_reclaim.go.
Follow-ups to expect
Situation. The directive was "feed materialization is a Kafka consumer writing to Cassandra." The service producing the activity is a Cloudflare Worker.
Action. Established first that Workers cannot open raw TCP sockets — so both the Kafka wire protocol and CQL are permanently unreachable, not merely awkward. That ruled out producing from the Worker at all. It also ruled out a dual write: a Worker cannot enlist Kafka in a Postgres transaction, so producing directly leaves a window where a post exists with no event, or an event survives a rolled-back post.
Result. A transactional outbox: the event row is written inside the
same transaction as the post; a host-resident Go relay claims, produces, and
stamps published_at. The relay produces before stamping — a crash between
the two re-delivers, which is deliberate, because a lost event cannot be
recovered and a duplicate can be absorbed. Each of the three consumers
absorbs it with a named mechanism.
Follow-ups to expect
Situation. Three things must happen when a user posts: it enters followers' feeds, it generates notifications, and it fans out to realtime listeners.
Action. The tempting build is one pipeline doing all three in sequence. That means a Cassandra outage stops notifications, and a notification failure keeps posts out of feeds. Instead: one topic, three independent consumer groups, each reading every event, each failing and retrying alone.
Result. All four processes run in one binary today because they share a database pool and a Cassandra session — not because they are coupled. Splitting them across hosts is a deployment change, not a rewrite.
Follow-ups to expect
Situation. The outbox table carries ~40 denormalized display columns for the activity-feed UI. The obvious move is to put them in the Kafka event so consumers don't have to join.
Action. Kept the event minimal — id, type, actor, target type, target id, timestamp. Consumers that need the actor's avatar join for it.
Result. Display fields are not frozen at write time. A user renaming themselves does not leave a trail of events carrying their old name forever.
Follow-ups to expect
Situation. A trained checkpoint is not a deployable model.
Action. Built promotion as a 9-gate evaluation — perplexity, BPC, token
accuracy, distinct-2, repetition rate, LAMBADA, HellaSwag, serving p95, and
throughput — with a data card recording contamination checks against the eval
suites themselves. Only when all nine pass is the checkpoint copied to
serving.pt, the image rebuilt against it, and the rollout performed.
Result. All 9 green; test PPL 90.0, p95 454 ms, 116 tok/s. The image on the cluster is provably the checkpoint that passed, via a SHA256 manifest.
Follow-ups to expect
serving.pt and its manifest are retained; rollback is an image tag, not a retrain.Situation. Auditing the WebRTC call path in a Go service.
Action. Found a concurrent map access in the call path. In Go this is
not a panic you can recover — it is fatal error: concurrent map writes, which
terminates the runtime. So it does not degrade one call; it drops every
connection on the host.
Result. Documented as G-07 in the gap register with severity and a remediation entry, rather than being papered over.
Follow-ups to expect
sync.Map for the read-mostly case; better, a single owning goroutine with a channel so the map is never shared at all.-race in CI, and the fact that this codebase has dedicated race tests (calling_race_test.go) is the answer to "do you actually do that."Situation. Porting a large iOS app to Kotlin/Compose, seven pre-existing defects surfaced in the original.
Action. Reproduced them deliberately in the port and wrote them down, instead of fixing them in passing.
Result. The two platforms stay behaviorally identical during the migration, so parity testing means something. The defects get fixed once, on purpose, on both platforms, as their own change.
Follow-ups to expect
Ask these; they signal the level you're interviewing at.