Mock 07 — Senior Engineer
Interview type: Senior SWE coding + design hybrid Target role: Senior Software Engineer (L5 Google / E5 Meta / SDE3 Amazon) Time limit: 60 minutes Format: ONE problem + system extension + explicit tradeoff discussion Hints policy: Hints on the algorithm lower your score significantly; hints on the extension are acceptable. Primary goal: Show senior-level reasoning — not just solving, but choosing among solutions with reasoning.
What This Mock Tests
At the senior bar, mere correctness is not enough. The interviewer wants to see:
- You consider multiple approaches and articulate why you chose one
- You understand the production implications of your choices
- You can extend the algorithm into a service-like context
- You can answer “what if the input is 1000× larger” with a concrete plan
Scoring weights: Tradeoff Reasoning (#13), Production Awareness (#14), Optimization (#4), Follow-ups (#11) are all critical. A senior who scores 3 on tradeoffs has signaled “mid-level”; needs 4+.
Pick One Problem
Problem A — Design a Rate Limiter
Build a rate limiter supporting allow(user_id, timestamp) → bool. Each user can make at most N requests per W seconds. Discuss the algorithm, then extend to a multi-server / distributed setting.
Initial constraints: in-process, single-thread. N ≤ 1000 reqs/window. W ≤ 60 sec. 1M users.
Problem B — Top K Frequent Elements (LC 347) + Streaming Extension
Phase 1: Given an array nums and integer k, return the k most frequent elements. O(N log K).
[1,1,1,2,2,3], k=2 → [1, 2]
[1], k=1 → [1]
Phase 2 (extension): the input is a never-ending stream; report top-k continuously with bounded memory. Discuss exact vs approximate tradeoffs.
Problem C — Snapshot Array (LC 1146)
Implement SnapshotArray:
SnapshotArray(length)— initialize withlengthzerosset(index, val)— set value at indexsnap() → snap_id— take a snapshot, return its idget(index, snap_id)— value at index at the time of snap_id
Discuss the algorithm; extend to a versioned key-value store with garbage collection of old snapshots.
Expected Communication Style
- Restate, including the implied requirements (“rate limit must be enforced even if the same user hits multiple instances”).
- Ask senior-grade clarifying questions: read-heavy vs write-heavy? Latency targets? Consistency requirements? Failure modes acceptable?
- Propose 2+ approaches with explicit tradeoffs. (“Token bucket vs sliding window log vs sliding window counter — I’d pick X because…”)
- State the algorithm and complexity.
- Code the chosen approach with senior code quality (clear naming, error handling at boundaries, no premature abstraction).
- Discuss the production extension without prompting.
- Anticipate failure modes — what breaks at 10× scale? 100×?
Solution Sketches
A. Rate Limiter:
- Sliding window log: per user, deque of timestamps. On request, drop entries older than
W, check length < N, append. O(N) per request (amortized O(1) drop). Memory: O(users × N). - Token bucket: per user,
(tokens, last_refill). On request, refilltokens += (now - last) × rate, cap at N, decrement if ≥ 1. O(1) per request. Slightly bursty. - Sliding window counter: approximate; uses 2 buckets (previous + current window), weighted by overlap. O(1), small memory.
Distributed extension: per-user state in Redis with atomic Lua script; or consistent-hash users to dedicated instances; or central counter with relaxed accuracy.
B. Top K Frequent:
- Static: Counter + min-heap of size K. O(N log K).
- Streaming exact: impossible with bounded memory in general (any element could become top-K later).
- Streaming approximate: Count-Min Sketch + heap of candidates; or Misra-Gries / SpaceSaving algorithm for ε-approximate. O(1/ε) memory.
C. Snapshot Array:
- Naïve: copy entire array per snapshot. O(length) per snap, O(snaps × length) memory.
- Better: per-index, store list of
(snap_id, value)pairs sorted by snap_id. Lookup with binary search. O(log S) per get, O(1) per set, O(total writes) memory.
Versioned KV store extension: persistent data structures (Clojure-style); or copy-on-write trees; or LSM-tree with snapshot isolation.
Common Failure Modes
- Implemented the first algorithm that came to mind without discussing alternatives. This is the #1 senior-bar failure.
- Said “I’d just use Redis” without explaining the algorithm Redis would implement. The interviewer wants the algorithm; the database is a deployment choice.
- Top-K streaming: claimed exact algorithm with bounded memory. Impossible in general; signals theoretical weakness.
- Snapshot Array: copied the array per snapshot. Acceptable as brute force; bad as final answer for a senior.
- No tests beyond the given examples.
- Skipped the production extension entirely.
Passing Bar
- Total score: 53/70 (average 3.8)
- Tradeoff Reasoning #13: ≥ 4
- Production Awareness #14: ≥ 4
- Optimal or near-optimal algorithm
- Extension discussed substantively (not just “I’d shard it”)
- Correct, readable code
Follow-up Questions
For A (Rate Limiter):
- Latency budget: < 1ms p99. → In-memory store; Redis is borderline (network RTT). Local cache with eventual sync.
- Multi-region with strict global limit. → Hard; usually relaxed to per-region limit + occasional reconciliation.
- What if Redis goes down? → Fail-open (allow) vs fail-closed (deny); usually fail-open for rate limiters.
- Hot user (one user makes 90% of requests). → Dedicated shard; or local fast path before checking shared state.
For B (Top K):
- Approximate with ε = 0.01. → Count-Min Sketch sized accordingly.
- Top K most-improved over the last hour. → Two-window comparison; bigger memory.
- Trending detection (top K with sudden growth). → Slope/derivative-based; needs time-windowed counts.
- What if K = 1M? → Heap-of-K doesn’t fit memory; external merge or sampling.
For C (Snapshot Array):
- Snapshot every write (versioned KV). → Same structure; consider compaction.
- Memory pressure: drop snapshots older than 1 hour. → Per-index list pruning; tombstones for fully-deleted snaps.
- Snapshot isolation in a multi-writer setting. → Multi-version concurrency control; per-transaction snapshot id.
- Persist snapshots to disk. → Log-structured store; periodically checkpoint.
Required Tests
- Given examples
- Empty / boundary input
- Heavy churn (many writes to same index for C)
- Single user / single key
- Burst of requests at the window boundary (A)
- K = N for B (no filtering)
Required Complexity + Production Discussion
Cover:
- Time per operation, space per user/element
- Latency under typical load vs worst case
- Memory growth and GC implications
- Failure semantics (what happens on partial failure)
- Monitoring metrics you’d add (rate limit reject rate, top-K convergence time, snapshot lookup p99)
Self-Evaluation Template
Mock 07 — Senior Engineer
Date: _______
Problem: _______
Time: ___ / 60 min
Scores (1–5):
___ Total /70
Tradeoff Reasoning (#13): ___
Production Awareness (#14): ___
Did I propose 2+ approaches before coding? Y/N
Did I anticipate scale-up failure modes? Y/N
Action item:
What to Do If You Fail
- Tradeoff or Production score below 4: Read Phase 8 (practical engineering) deeply; rebuild a small system (rate limiter, cache).
- Algorithm score below 3: You haven’t earned the right to do senior interviews yet; back to Mock 04–06.
- Code quality issues: Read CODE_QUALITY.md.
- Pass twice consecutively before Mock 08.