Tower Research's Streaming Failure Detector
Tower Research likes streaming data-structure problems that have to run forever without leaking. This failure detector watches an infinite log stream and alerts on three failures inside a window, then the interviewer pushes on memory and scale. Here is the full question, Java for each part, and a detailed rubric.
The question
From an infinite stream of logs like 01:00:01 user_a login failure, detect when a user has three consecutive failures within five seconds and raise an alert. A success resets that user's streak.
Part 2: bound memory. Part 3: scale to a very large number of users.
Part 1 · Per-user sliding window
Keep a deque of recent failure timestamps per user. On a failure, append and evict anything older than the window; on a success, clear the user. Alert when the window holds at least the threshold.
import java.util.*;
class FailureDetector {
private final int threshold; private final long window;
private final Map<String, Deque<Long>> failures = new HashMap<>();
FailureDetector(int threshold, long window) { this.threshold = threshold; this.window = window; }
boolean process(long ts, String user, String event) {
if (!event.equals("failure")) { failures.remove(user); return false; } // success resets streak
Deque<Long> dq = failures.computeIfAbsent(user, k -> new ArrayDeque<>());
dq.addLast(ts);
while (!dq.isEmpty() && ts - dq.peekFirst() > window) dq.pollFirst(); // evict stale
return dq.size() >= threshold && (dq.peekLast() - dq.peekFirst() <= window);
}
}
Part 2 · Bound the memory
Two leaks hide here. A single user's deque should never exceed the threshold, and users that stop failing should not linger forever. Cap the deque, drop empty entries, and sweep idle users.
boolean process(long ts, String user, String event) {
if (!event.equals("failure")) { failures.remove(user); return false; }
Deque<Long> dq = failures.computeIfAbsent(user, k -> new ArrayDeque<>());
dq.addLast(ts);
while (!dq.isEmpty() && ts - dq.peekFirst() > window) dq.pollFirst();
if (dq.size() > threshold) dq.pollFirst(); // never store more than we need
if (dq.isEmpty()) failures.remove(user); // drop emptied users
return dq.size() >= threshold && (dq.peekLast() - dq.peekFirst() <= window);
}
// Periodic sweep: forget users whose newest failure has aged out of the window.
void evictIdle(long now) {
failures.entrySet().removeIf(e -> now - e.getValue().peekLast() > window);
}
Per-user memory is now O(threshold), a tiny constant, and total memory is bounded by the number of recently active users rather than everyone ever seen.
Part 3 · Scale to many users
The state is partitioned cleanly by user, so it shards. Hash each user to one of N workers and every event for that user lands on the same worker, which keeps its stream ordered and its window correct without cross-worker coordination.
- Sharding. Route by
hash(user) % Nso per-user ordering is preserved on a single worker, and the detectors run fully in parallel. - Out-of-order events. If timestamps can arrive slightly out of order, hold a small reorder buffer per shard and process in timestamp order, or accept bounded lateness.
- Hot keys. A single very busy user stays within O(threshold) memory, so no shard blows up.
How Tower Research scores it
| Dimension | Weak | Strong |
|---|---|---|
| Window correctness | Counts failures across the whole stream | Per-user window, success resets the streak |
| Amortized cost | Rescans timestamps each event | O(1) amortized with deque eviction |
| Per-user memory | Unbounded deque growth | Capped at the threshold |
| Total memory | Keeps every user forever | Drops empty and idle users |
| Scaling | Single-threaded only | Shards by user, preserves per-user order |
| Edge cases | Off-by-one at the window edge | Handles exact-window and out-of-order arrivals |
This is one question of 21 pages
Get the full Tower Research question bank
The full Tower Research bank carries the data-structure, systems, and probability rounds, each problem with its follow-ups and a rubric, compiled from people familiar with the process and cross-verified across sources.
Tower Research interview FAQ
What does the Tower Research coding interview ask?+
Streaming and systems data-structure problems, cache hierarchies, and probability. The failure-detector question tests a correct per-key sliding window with amortized O(1) updates and bounded memory over an unbounded stream.
How do you keep the failure detector's memory bounded?+
Cap each user's window to the threshold count, drop a user's state when it empties, and periodically evict idle users. Without these, an infinite stream of distinct users grows memory without limit.
How is the Tower Research coding round scored?+
On a correct sliding window with success resetting the streak, amortized O(1) per event, bounded per-user and total memory, a credible scaling story (sharding by user, out-of-order handling), and boundary edge cases.
Where can I find real Tower Research interview questions?+
Pichup maintains a 21-page Tower Research Capital question bank compiled from people familiar with the process, with the data-structure, systems, and probability rounds, their follow-ups, and rubrics. The question in this guide is one of them.