Most "use Redis" answers in system design interviews are one step ahead of the question. A hotel room hold is the classic case: ten minutes, one row, one expiry timestamp. A database already does this. Redis earns its place only when a specific thing starts to hurt — and knowing what that thing is is the difference between naming a technology and making a design decision. Episode 1 of Design Decisions breaks it down in 2 minutes, including what to actually say in an interview.
Formation
Professional Training and Coaching
San Francisco, California 16,261 followers
Formation is the world's first AI-powered platform helping experienced software engineers land lifechanging tech roles.
About us
Formation is the world’s only AI-powered dynamic interview prep platform, providing unlimited benchmarking, personalized skill development, and world-class mentorship to accelerate peoples' engineering careers. Since June 2020, with Formation’s hyper-personalized learning approach, 550+ engineers have found success landing at companies across the tech industry. Some of these companies include Meta, Google, Twitch, Dropbox, Adobe and Figma among many others. Formation knows that every engineer is coming to the table with different experiences and a different way of learning. Formation's patented adaptive learning algorithm takes that into account and creates a dynamic interview prep roadmap to focus an engineer's efforts on the exact skills they need to develop at the exact right time. Thanks to this hyper-focused and personalized approach, Formation has successfully helped shape peoples' career paths for those with minimal experience to 17+ years of experience, unlocking prestigious roles at top-tier companies for ambitious engineers.
- Website
-
https://formation.dev
External link for Formation
- Industry
- Professional Training and Coaching
- Company size
- 11-50 employees
- Headquarters
- San Francisco, California
- Type
- Privately Held
- Founded
- 2019
- Specialties
- Computer Science Education
Employees at Formation
Locations
-
Primary
Get directions
San Francisco, California, US
Updates
-
Everyone is now calling verification the new core engineering skill. Almost nobody has published an actual procedure for it. Here's the framing that makes it work: treat AI-generated code like output from a fast teammate whose work you haven't checked. Not an oracle. Not a toy. Usually close — occasionally wrong in ways that look completely fine. Reviewing it well is a repeatable loop, not a vibe. Step one: review the highest-risk areas first. Algorithm shape, loop boundaries, and whether the code actually matches the requirement. Not style. Style is the most visible layer and the least likely to hurt you. Step two: test against a real case list. Happy path, boundaries, equivalence classes, adversarial input. And a trap worth naming: generating test code and verifying correctness are different activities. Asking the model for tests is not the same as knowing the code works. Step three: choose your repair mode. This is the judgment call most people get wrong. Small bugs — a wrong index bound, a missing empty-input guard — fix by hand. It's faster, and it builds the understanding you'll need to defend the code. Major logic problems — don't patch piecemeal. Re-prompt with four things: the exact failing test case, observed versus expected output, the intended algorithm, and the complexity requirement. All four, not two. Underneath all of it: ask for one bounded piece at a time. Decomposition is what makes code reviewable — from models and from humans. And if AI is banned in your interviews, this loop still is the thing being graded. Testing assumptions and reasoning about boundary cases is what interviewers were always evaluating. Full write-up with the loop as a one-page checklist: → https://fm.dev/4irEAKX
-
AI-assisted interview rounds have moved from experiment to pilot at major companies — including formats where you're handed an AI assistant and evaluated partly on how you use it. At the same time, the consensus is that AI has eroded the signal from traditional coding rounds. Both facts point at the same conclusion: the question changed from "can you solve it" to "can you direct, explain, and verify it." When a model produces working code in seconds, typing speed and memorized syntax stop separating anyone. So here's what replaced them. Clarifying questions became the whiteboard skill. Interviewers are watching whether you interrogate an ambiguous requirement before writing anything. Control is what's being scored. Did you choose the algorithm and the architecture? Can you defend the trade-offs, even when the model typed the implementation? A candidate who accepts a working solution they can't justify scores badly — working solution notwithstanding. Confident and wrong is the failure mode. AI-generated code and explanations read authoritatively while being incomplete or incorrect. Complexity claims especially: frequently asserted, rarely verified. You have to actively check edge cases and hidden assumptions. The working pattern that reads well is small and reviewable. State your intent. Request a bounded piece. Read it. Test it. Then continue. The opposite — asking for the whole solution and hoping — is visible from across the room. Here's the part that should be reassuring: judgment about data structures, trade-offs, and edge cases transfers completely. Rote implementation practice matters much less than it did. And if your target company bans AI in interviews entirely, the habits are identical. Testing assumptions and reasoning about boundary cases is what was always being evaluated. → https://fm.dev/45K83bJ
-
Twelve months ago, "design a system that serves an LLM" was an ML-role question. It's now showing up in general software engineering loops, and at AI-first companies it can be an entire round. Candidates are responding by cramming transformer architecture. That's preparation for a question nobody is asking. When an interviewer asks you to design an AI-powered feature, they're testing system design judgment. The AI is a dependency — expensive, slow, non-deterministic, and occasionally wrong. Everything being scored is about how your system behaves around that dependency. Which means it's a distributed systems problem in a new shape. You already know how to reason about it. Four things earn points: Latency. LLM calls run an order of magnitude slower than a normal API call. What's your timeout? What does the user see while waiting — streaming or blocking? Cost. Token cost is per-request and non-trivial. When do you cache, and what's the cache key when the input is natural language? When do you route to a smaller model? Failure. The model returns nothing, returns slowly, or returns something confidently wrong. Those are three separate failures. Name them separately. What degrades, and what's the fallback path? The correctness boundary. What in this system is allowed to depend on model output being right, and what has to be verified before it reaches a user? Talk about RAG as retrieval and generation — two stages, each with its own latency and failure budget — not as a lecture on embeddings. And the failure modes seniors are expected to raise unprompted: circuit breakers around the provider, graceful degradation to a non-AI path, and a monitoring story for output quality, not just uptime. What to actually study is a short list, and it's mostly things you already know. → https://fm.dev/3SukRja
-
"It's AP." Two words, and the interviewer already knows how deep your understanding goes. CAP is the most-cited and least-understood idea in a system design interview. Three specific misunderstandings show up over and over, and each one produces a worse answer than saying nothing at all. Availability does not mean "the data is there." In CAP, availability means only that the system returns a successful, non-error response. It says nothing about whether that response is current. An available system will hand you a stale account balance with total confidence. CAP consistency is not ACID consistency. CAP consistency is about what values reads can return across replicas. ACID consistency is about preserving invariants inside a transaction. Same word, unrelated concepts — and conflating them is a visible tell. CAP is not a permanent "pick two." It describes the trade-off during a network partition, not a standing property of your system. Partitions are effectively unavoidable, which is exactly what makes this a practical design question instead of a theoretical one. Here's what the trade-off actually looks like when it's concrete: A bank balance should reject requests rather than risk a double-spend. A shopping cart or a likes counter should keep accepting updates and reconcile conflicts later. Same architecture, opposite call — and the reason is the business consequence of being wrong. So instead of "it's AP," try the sentence that shows you've made a decision: "During a partition, this subsystem should reject writes, because the cost of a stale read here is X." And the part that reads as senior: one product usually needs both. Naming which subsystem gets which is the move. Full breakdown, including what to say when the follow-up comes: → https://fm.dev/4qpPVxf
-
"I'd shard the database." One follow-up question punctures that answer: shard by what? A partition key is not a technical detail. It's a statement about which access patterns matter — and it's the hardest thing in your system to change later. Choosing one means choosing which queries you make cheap and which you accept as permanently expensive. There is no universally correct key. There are only trade-offs you can name: Shard by parent ID (advertiserID, tenantID). Co-locates related data, avoids distributed transactions, makes "everything for this tenant" a single-shard query. Breaks any lookup that doesn't already know the parent ID. Risks badly uneven load. Shard by the entity's own ID. Beautiful even distribution for point lookups. Turns every relational query — "all campaigns for this advertiser" — into a scatter-gather fan-out across every shard. Shard by timestamp or range. Great for time-range scans. Puts a hotspot on the newest partition, which is exactly where all your write traffic lives. Three things that separate a senior answer: The jumbo tenant. One dominant customer outgrows its shard. Now you're doing composite keys or tenant splitting, under pressure, on live data. Name that risk before the interviewer does. Hot shards and hot keys are different problems. Hashing fixes uneven shard sizes. It does nothing for one wildly popular key. Constantly conflated. The resharding tax. Growing a sharded database is a migration project, not a config change. Nobody mentions this upfront and everybody pays it. Anyone who says "shard by ID" without naming what that breaks hasn't made a decision. They've picked a default. The full reference piece — three strategies, the trade-offs, and a four-question checklist for choosing a key live in an interview: → https://fm.dev/3U6T3Sz
-
"If the leader dies, we promote a follower." Then: how do you know it died? And who decides? Failover sounds like an operation. It's a distributed consensus problem wearing a simple name — and done carelessly it produces two failures worse than the outage it was meant to prevent. Split-brain. Two nodes both believe they're the leader. Both accept writes. Both are correct from where they're standing. You now have two divergent histories of the same data and no automatic way to merge them. The zombie leader. The old leader was never dead, only unreachable. It comes back, still believing it's in charge, and overwrites newer data written to the new leader. The dangerous word there is silently. Nothing errors. No alert fires. You find out later, from the data. Why almost nobody catches these before production: each one needs a partition, plus a promotion, plus a specific ordering of events. They don't reproduce in staging. What actually prevents them — fencing tokens, quorum-based leader election, STONITH — all reduce to one principle: a node must be able to learn that it has been superseded. And this is the sentence that changes how a panel reads you, offered unprompted: "For failover I'd want fencing, because the failure I'm worried about is the old leader coming back and overwriting." Failure modes are being graded explicitly this year. Almost nobody brings this one up on their own. Full write-up, with the split-brain and zombie leader timelines diagrammed: → https://fm.dev/4qmg4wO
-
"The database is struggling." "I'd add a read replica." That exchange happens in thousands of interviews a week, and the follow-up question is always the same one candidates haven't prepared for: what, specifically, is growing? Reads, writes, data size, and geographic reach are four different problems with four different answers. Prescribing before diagnosing is the mistake. Because here's the thing about replicas: in a standard single-leader setup, they add exactly zero write capacity. Every write still funnels through one leader. Ten followers, one leader, same write ceiling. If writes are what's growing, replicas buy you nothing. Two more things worth knowing before you reach for them: Replicas don't mean fresh. Freshness comes from explicit guarantees — quorum commit plus a read-consistency policy. The existence of follower copies guarantees nothing on its own. Sync vs. async isn't a performance question, it's a choice of failure mode. Async means you can lose writes on failover. Sync means higher write latency and reduced availability. There is no third option where you get both. Naming which one you're choosing is the answer. The senior move is refusing to pick one policy for the whole system. Payment status needs leader reads for strong freshness. A social feed serves stale follower reads happily. Same cluster, different read policy per subsystem. And before any of it: indexes and caching. Exhausting the boring fixes first reads as experience, not avoidance. The full walkthrough — including how to answer the "what's actually growing" follow-up: → https://fm.dev/4zrAj0f
-
Holding a million WebSocket connections is a solved, boring problem. That's not the hard part of real-time systems anymore — and treating it as if it were is a tell in an interview. The hard part: delivering one message to a user whose socket happens to live on a different server than yours. "Add a message broker" is where most answers stop. It's actually just the start. Here's the piece people skip: Redis Pub/Sub will happily broadcast your message to every server. It will not tell you which server holds user 4,821's connection. You still need a separate presence registry — a stateful component, with its own consistency and failure questions, mapping users and rooms to servers. A few things that separate a senior answer from a mid-level one: Kafka is a poor fit here. It's built for a manageable number of topics and partitions, not millions of individual routing targets. Redis Pub/Sub is at-most-once and non-durable. If you need delivery guarantees or reconnect replay, you're pairing it with Streams, JetStream, RabbitMQ, or a database. Colocating room members on one server kills the fanout problem locally — but creates hot-room risk and a large blast radius when that server dies. The candidates who separate themselves aren't the ones who name a broker fastest. They're the ones who ask "which server holds this user" before anyone else in the room does. We wrote up the full three-stage progression — from one server to colocation to broker-plus-registry. → https://fm.dev/3TLgVLq
-
WebSockets are the most efficient option per message. They're also frequently the wrong answer — and knowing why is exactly the judgment interviewers are scoring for this year. Here's the trap: WebSockets win the metric everyone measures. Then the bill arrives for the metric nobody measured. An idle WebSocket isn't free. It holds memory and a file descriptor on your server whether or not a single byte is flowing through it. Multiply that by 100,000 mostly-idle clients, and polling — the "worse" option — can win on total cost. So where's the crossover? It comes down to message frequency times client count: Infrequent updates, huge audience → polling wins. One-way updates, near-real-time → SSE is the underused middle. Built-in reconnect, runs over standard HTTP, no new load balancer. High-frequency, bidirectional → WebSockets earn their keep — but budget for sticky routing, WebSocket-aware load balancers, and backpressure handling. That's not free either. The strongest answer in an interview isn't "WebSockets are real-time so they win." It's naming the trade explicit, in two sentences. We wrote out the full crossover math — where each option wins and why. → https://fm.dev/3SmgYwK