Skip to content

On system design preparation

Posted on:July 5, 2025 at 03:22 PM

System design interviews are the trickiest of all engineering interviews because they don’t have an objective judgement, or so people think. Two months ago, I found myself at a spot where I had two system design interviews scheduled on a two-day notice and I had no idea how to answer a system design interview. While I knew what a system design interview expects, having interviewed many people, I didn’t know what it actually feels like to be in the shoes of a candidate. Building systems is one thing, but condensing the solution to an absolutely vague real-world problem into a ~45-minute episode felt quite intimidating. So I put together a short plan for the next two days, blindly put my faith in it, and decided to just go on grinding at it.

Turns out it was a decent plan. I learned a fair bit and felt like I was interview-ready by the end of those two days of prep. When I started my prep, I couldn’t find much material that wasn’t just theoretical or checklist-driven, so I thought I’d share something simple and principled for others who might find it useful.

Disclaimer: This is about the process of preparation and presentation for system design interviews, not about solving the engineering problems themselves.

When I conducted system design interviews, I’d look for these qualities in a candidate. Naturally, my effort was to showcase the same when I interviewed myself:

  1. Good technical depth in some area
  2. Ability to clearly articulate technical ideas
  3. Sound engineering first principles
  4. Courage to work through ambiguity
  5. A spark of joy while solving problems

Operating Principles

Before we get into the actual plan, I feel one should go into any pursuit with some operating principles. They act as cornerstones as you wrestle through tough times. I follow a few principles while brainstorming at work and they seemed to fit in well in system design rounds as well:

Smile: Yes we’re all nervous during a stressful encounter where someone is trying to evaluate us. Research suggests that a subtle smile can go a long way in comforting both, yourself and the person that you’re interacting with. Smiling could possibly be understood as a convenient and tranquilizing form of human action which has abundant therapeutic value and potential for enhancing the individual, dyadic and societal contexts to a great extent. Believe it or not, your system design solution is evaluated by a human being and as much as they will try to be objective, I think that setting a positive tone to the entire conversation can be a big gamechanger in the interaction. Similarly, thinking out loud not only communicates your ideas to the interviewer, but also helps build trust with them. You must build a rapport with the interviewer where both of you are comfortable with brutally challenging each other for it to be a productive encounter. Smile and build trust with them :)

Grok the problem before even thinking of the solution: While this may seem obvious, it really is not. Our brain is wired to jump onto a solution immediately at the first glance of a problem, and the first glance is often deceptive or incomplete. This impulse to jump onto a solution has served quite dangerously for me in the past, both in personal and professional contexts. So it’s important to keep reminding yourself to pause and understand the problem before starting to think of a solution. We can either assume the unknowns and call it out, or just blatantly ask if something is not clear. Asking for help might come off as vulnerability to some, but I believe asking for help is an act of humility and trust-building. Call-out, ask, clarify — do whatever it takes to understand the problem before solving it. For instance, if there’s a problem of building a social media feed, your brain will instantly pop a fan-in/fan-out approach into your head, while this might not even be necessary for the scale that this app demands.

Solve the problem like you’re telling a story: You can be the most solid engineer with the right solutions, but it’s all in vain if the interviewer cannot understand what you’re trying to convey. So it’s very important to take the interviewer along as you explore your thoughts and different solutions. All of us love stories. An interesting story is the single best way to keep your audience engaged and interested in what you’re trying to say. This holds especially true if you’re talking about something unconventional or novel. People tend to get slightly uncomfortable when they see something unconventional or groundbreaking. But if it’s part of a story and the unconventional approach fits in well, your audience will acknowledge it, if not appreciate it. Let’s say, for instance, the problem is to build a notification system in an HRA app. You can start the story with something like: “So imagine there’s an HRA app used by companies, and they have to repeatedly go to their dashboard to see updates of their documents, reimbursements, etc., and they’re a little frustrated about it. We have to pacify them by enabling them to receive these updates on their communication channel. What would they most prefer? Email? Slack? SMS?…”

In case of ambiguity, first make it work, then make it great: There are times when there’s a hard problem, you can’t think of a good solution to it, and the timer is ticking. Tick tock — anxiety. The single best approach in these situations is to just start with a brute force solution and tell the interviewer that this works but it’s slow or costly. Once you verify that it works, you can observe the bottlenecks that are adding to the cost and then try addressing them. Despite being just brute force, writing out the solution helps build a deeper intuition of the problem, after which you are in a better position to come to a more optimal solution.

Use experience for depth, use concepts for breadth: Everybody has limited experience. Nobody has worked with Postgres, MySQL, MongoDB, Cassandra, Firebase, ClickHouse, and Aerospike all in depth and at scale. I don’t think interviewers expect you to know everything either. I’ve personally only worked with Postgres, Mongo, and Redis at serious depth. So it’s counterproductive to go deep into the specifics of technologies you’ve never used. It’s a sure way to shoot yourself in the foot. Instead, it’s more productive to talk about high-level concepts you understand about the unfamiliar tech and draw parallels with systems you understand deeply. For example: “We need a write-heavy AP database for this problem, so I’d choose DynamoDB, though I haven’t used it in production. Like in Postgres, I’d design my access patterns carefully to avoid performance hotspots. I know Dynamo uses partition keys to distribute load and supports different consistency levels. I’d also look into how indexing and capacity provisioning work in DynamoDB to ensure it works for our scalability needs.” This shows that I understand DynamoDB through first principles without digging my own grave by wading into specifics I haven’t worked with. If they ask anything about Postgres, I can go as deep as necessary, but for Dynamo, I’ve framed my answer to stay at the conceptual level.

The plan

It was Friday. I had 2 days left, with zero system design interview experience. For a good two hours, I was intmidated and brooded on the thought of postponing these interviewes for a good hour. But I didn’t want to extend the learning cycle all that much and know where I stand currently. Immediately, I put together a plan:

  1. Generate 10 diverse system design problems
  2. Divide each day in 5, 2 hour focus windows
  3. Spend each focus window dedicated to one system design problem, while continuously getting better
  4. Solve last two problems with a real interviewer (a friend)

Generate practice problems

ChatGPT Prompt: “I’m a Staff Engineer. Give me 10 diverse problems that I should use to practice for my upcoming system design interviews. Each problem must be vague and described in 1-2 lines.” This is what I got: Absolutely—here are 10 diverse system design problems for you to sharpen your skills:

a. Design a URL Shortener: Build a system like Bitly that maps long URLs to short codes, with redirection and analytics.

b. Design a Distributed Cache: Create a caching service like Redis or Memcached supporting high availability and consistent eviction.

c. Design a Notification System: Architect a platform to send email, SMS, and push notifications reliably and at scale.

d. Design a Rate Limiter: Build a service to enforce per-user request quotas with configurable limits and sliding window support.

e. Design a Real-Time Chat Application: Design WhatsApp-like messaging with typing indicators, message delivery guarantees, and read receipts.

f. Design a News Feed System: Create a Facebook-like feed aggregating posts, ranking them, and supporting infinite scrolling.

g. Design a Video Streaming Platform: Architect YouTube-style upload, storage, transcoding, and delivery with adaptive bitrate streaming.

h. Design an API Gateway: Build a gateway handling authentication, routing, throttling, and monitoring across microservices.

i. Design a File Storage Service: Design Dropbox-like file storage with versioning, sharing, and conflict resolution.

j. Design a Search Autocomplete Service: Create Google Search-style suggestions based on partial queries, popularity, and personalization.

These are generic problems, but it wasn’t about the problems — this exercise was just to brush up the latest developments in technology and build a muscle memory for solving problems in a structure with the above operating principles.

Focus Window

Each focus window was aimed at solving the given problem and continuous learning. The focus window was divided into: Solve in 45 minutes with the right structure, Reflect and rate myself for 15 minutes, Read and learn 1 hour.

For solutions, I broke down my approach into the following segments. This is similar to most system design literature out there, but anyway:

  1. UGIO: Talk about the users we’re building this for, the one-line goal, and the input/output interface. This would help me build a story around it. For example, for a notification system in product X: “So we’re building for users of X to receive updates and also the developers of X to emit notifications easily. The main goal is to emit notifications on important events. The interface for the notification system can be an API/SDK for developers, and users can receive notifications on the medium of their choice.”

  2. Functional Requirements: Talk about the behavior of the system as end users would see it. For example: “This system should be publish a schema of supported notification channels. This should be able to send notifications on one of the supported channels. Credentials might or might not be persisted by this system. Lets think if it’s the responsibility of notification system to persist credentials”

  3. Non-Functional Requirements: Talk about the latency, throughput, traffic, cost, and everything else you need to understand to come up with an architecture that scales for the foreseeable future (not indefinitely). I’d only ask for DAU and peak traffic. You could also do capacity requirements at this stage, but I’d usually do it on the go if needed, unless it’s an analytics use case.

  4. Primitives: The core engineering primitives that would power the entire system. We only need the core primitives here, not the entire DB schema. We can design the schema if necessary after we have a good sense of where the system design is going. Settling on the entire schema initially makes things very rigid and causes a lot of back and forth. Think deeply about the primitives such that you don’t have to change the primitives — other things can stay fluid.

  5. High-Level Design: Draw different components of the system—client, services, databases. Choose microservices vs monolith. Do not introduce cache unless absolutely necessary. People tend to randomly introduce a cache, which pisses me off a bit as an interviewer, but suit yourself.

You should reach step 5 ~25 to 30 minutes. In the last 15 minutes, I’d deep dive into the area that forms the core of the entire system, what gives this system a business advantage and is mission critical. This could be about improving latency by introducing cache, async processing to throttle load and save resources, database performance, frontend cache for slick experiences, polling/websocket/server-sent-events in an SDK for real-time experiences, or whatever else.

After the deep dive, I’d reflect on my solution for 15 minutes, rate myself out of 10, and read up about the area I struggled the most in for the next hour. The best way to learn, I felt, was reading the top 5 articles related to the topic on Hacker News, followed by reading the HN discussion. Another thing I did was just to brainstorm with ChatGPT about a topic and keep going deeper. It was super fun learning.

I repeated this for all 10 problems, and towards the end I felt confident that I can solve most system design problems. Learned a lot about the practical implications of the CAP theorem, Aerospike, how Clickhouse stores data, what happens if a Mongo node goes down, why microservices make sense only after a team size > 100, Yugabyte’s internals, and a lot more things. Some interesting resources:

  1. The CAP Theorem. The Bad, the Bad, & the Ugly
  2. Database Storage Engines
  3. Postgres vs MySQL
  4. In-Memory vs Disk-Based

I cleared the two scheduled interviews and the interviewers seemed very happy with the interaction. I answered two more after that and cleared them as well. Three of these eventually turned into offers, and by now, I feel like I have a much better sense of what it takes to answer a system design round well. In the end, I don’t think there’s any shortcut to getting better at system design. The process and structure can help you show up confidently and make the most of what you already know, but the real foundation is simply spending time building real things for real problems. That’s a long, imperfect journey, and it’s what makes this craft so endlessly fascinating. None of us will ever have all the answers, and that’s probably the beauty of it. We just keep learning, one problem at a time.