Clarify Requirements

What the interviewer just asked

You paused after the prompt. Now gather requirements — write them on the board so the interviewer can course-correct early.


Functional questions to ask

  1. How does the client receive prices? Server-Sent Events (SSE) — one persistent HTTP connection, server pushes events. Spring’s SseEmitter is the natural Java handle.
  2. How many connections per user? One. All watched symbols share a single SSE stream.
  3. How does the client register symbols? REST calls after connect: add one symbol, remove one symbol, or replace the entire list (page switch).
  4. What does a price event look like? JSON payload with symbol and price; the client routes by symbol field.
  5. What happens on page switch? Old watchlist is discarded; new list replaces it in one call — not ten sequential deletes and adds.
  6. Does the server generate prices or receive them? Assume an upstream feed calls publish(symbol, price) — your job is fan-out to subscribed users, not market data ingestion.
  7. What if the user connects but watches nothing? Connection stays open; no events until they call POST /watch.

Non-functional questions

  1. Single JVM or distributed? Start in-memory, single process unless they insist on multi-node.
  2. Thread-safe? Yes — connect, watch, disconnect, and publish can run on different threads concurrently.
  3. Latency expectations? Sub-second fan-out from tick arrival to SSE push is fine for a watchlist UI.
  4. Delivery guarantee for a single tick? At-most-once is acceptable — if a user misses one price during a page switch, the next tick arrives. Confirm this explicitly; it affects whether you need a per-user lock on replace.
  5. How many users / symbols? Order of thousands of concurrent connections, tens of symbols per user — in-memory maps are sufficient for v1.
  6. What happens on reconnect? Page refresh opens a new SSE connection; old emitter is completed and state is cleaned up on disconnect callback.

What you produce on the board

Functional

  • GET /connect?userId=U1 — open SSE connection; return SseEmitter
  • POST /watch?userId=U1&symbol=AAPL — add symbol to user’s watchlist
  • DELETE /watch?userId=U1&symbol=AAPL — remove symbol from watchlist
  • PUT /watch?userId=U1 body ["MSFT","GOOGL","AMZN"] — replace entire watchlist
  • Internal publish(symbol, price) — fan out to all users watching that symbol
  • On disconnect (tab close, timeout, error) — remove user from all maps

Non-functional

  • Thread-safe registry for concurrent connect/watch/disconnect/publish
  • In-memory, single JVM for v1
  • One SSE connection per user
  • O(1) fan-out lookup by symbol via symbolUsers map
  • At-most-once tick delivery acceptable during page switch (unless interviewer says otherwise)

Out of scope (say explicitly)

  • Multi-region deployment
  • Durable message replay or event sourcing
  • Kafka / Pulsar / Redis Pub/Sub as the primary design (discuss in scale-out section)
  • Authentication and authorization
  • Rate limiting on watch API
  • Historical price charts or persistence

Board checklist

Copy this structure onto the whiteboard and tick items as you build:

[ ] APIs: connect, add, remove, replace
[ ] Three maps: userEmitters, userSymbols, symbolUsers
[ ] connect() — register emitter, init symbol set, wire callbacks
[ ] disconnect() — remove emitter, unregister from all symbols
[ ] addSymbol() / removeSymbol() — update both maps
[ ] replaceSymbols() — tear down old, register new
[ ] publish() — symbolUsers → userEmitters → emitter.send()
[ ] Thread safety — ConcurrentHashMap + newKeySet()
[ ] Page-switch race — gap acceptable? per-user lock if not

Scope sentence you can say out loud

“I’ll build a single-JVM stock price fan-out service with one SSE connection per user. REST endpoints manage the watchlist; three concurrent maps form a bidirectional index between users and symbols. On disconnect, I clean up all registrations. On publish, I look up watchers by symbol and push to their emitters. I’ll call out the page-switch gap and when a per-user lock is needed, then mention Kafka or Redis only if we need to scale beyond one JVM.”