−65% Most banks now $169 $59.
Coding · 8 min read

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) % N so 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 correctnessCounts failures across the whole streamPer-user window, success resets the streak
Amortized costRescans timestamps each eventO(1) amortized with deque eviction
Per-user memoryUnbounded deque growthCapped at the threshold
Total memoryKeeps every user foreverDrops empty and idle users
ScalingSingle-threaded onlyShards by user, preserves per-user order
Edge casesOff-by-one at the window edgeHandles 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.