Interview Method • Scaling & Caching • Data & Messaging • Classic Designs • 2026

System Design Interview Questions

32 questions What each one tests, an answer frame, a spoken answer 41 min read

This page is for engineers preparing for a system design round, from a first backend role to a senior position. Most rounds test the same core: how you gather requirements and estimate load, how you scale with load balancers, caches, replicas and shards, how you reason about consistency and queues, and how you handle a classic design such as a URL shortener, a feed or a chat system. Senior rounds push harder on trade-offs and failure. Each question shows what the interviewer is really checking, the shape of a strong answer and a short answer you can say out loud. Practise drawing while you talk.

Search all questions by round, difficulty and level, or save the ones you want to practise.

Interview Method 4 questions

Easy System design round Fresher, Mid-level, Senior Practice question

1. You have 45 minutes to design a system you've never seen before. How do you spend that time, from your first question to the end?

What the interviewer is really testing:
Whether you can drive an open-ended conversation with a clear structure instead of jumping straight to boxes, and leave time for the deep dive where most of the signal is.
Answer frame:

Requirements: core features, who uses it, scale, and which qualities matter most. Agree what's out of scope.

Estimates and API: rough load and storage, then the handful of calls the system must support.

High-level design: data model, main components, and one request traced end to end.

Deep dive: the hardest part, its failure modes and trade-offs, and what changes at ten times the load.

Sample spoken answer:

"I start by asking questions, not drawing. I pin down the core features, who the users are, roughly how many, and whether reads or writes dominate, and I agree what's out of scope. Then I do quick estimates, just enough to know whether this fits on one database or needs sharding, and I sketch the main API calls. Next I draw the high-level design: clients, load balancer, services, data stores, caches and queues, and I walk one request through it. That usually gets me to about the halfway mark. The rest is the deep dive, where I pick the hardest part, like how the feed is built or how we avoid sending a message twice, and talk through failures and trade-offs. I check in with the interviewer at each step so I spend time where they care, and I say my assumptions out loud."

Red flag to avoid:

Naming technologies and drawing boxes in the first minute without asking a single question about scope or scale.

They may ask next:
  • If the interviewer gives you no numbers at all, what do you assume and how do you say it?
  • How do you decide which component deserves the deep dive?
Say it in 60 seconds
Easy System design round Fresher, Mid-level Practice question

2. What's the difference between functional and non-functional requirements? Show me using a food delivery app.

What the interviewer is really testing:
Whether you know that qualities like latency, availability and consistency shape the architecture far more than the feature list does, and that they differ per feature.
Answer frame:

Functional: what the system does: search restaurants, place and pay for an order, track the driver.

Non-functional: how well it must do it: latency, availability, consistency, durability, peak load, security.

Per feature: say which quality wins where, because payments and driver tracking need very different things.

Sample spoken answer:

"Functional requirements are the features. In a food delivery app, a customer searches restaurants, places and pays for an order, and watches the driver on a map. Non-functional requirements describe how the system must behave while doing that: how fast search responds, how available ordering is at dinner peak, whether a payment can ever be lost, how many orders a second we must handle. Those drive the design more than the features do, and they differ by feature. Payment needs strong consistency and durability, so it belongs in a transactional database. Driver location updates every few seconds and a slightly old position is fine, so I'd optimise that path for write throughput and accept eventual consistency. In an interview I list three or four features, then ask which qualities matter most, because that tells me where the hard part is."

Red flag to avoid:

Listing only features, or saying the system must be 'scalable and highly available' without saying which part, how much, or what gets traded away.

They may ask next:
  • How would you turn 'the app must be fast' into something you can actually measure?
  • Which requirement would you cut first if you had to launch in half the time?
Say it in 60 seconds
Medium System design round Fresher, Mid-level, Senior Practice question

3. You've agreed the requirements for an event ticket booking system. Before drawing any servers, walk me through the API and the data model.

What the interviewer is really testing:
Whether you can turn requirements into a small, concrete API and data model, and let them expose the hard part of the design before any boxes appear.
Answer frame:

API: only the calls the core features need: view seats, hold seats, confirm a booking with an idempotency key.

Entities: events, seats, holds and bookings, with their keys and the status each one needs.

Store choice: booking needs transactions, so a relational database; the seat map can be read from a cache.

Hard part: one conditional update so two people can never hold the same seat.

Sample spoken answer:

"I keep the API small. One call returns an event's seat map with each seat's status. A second call holds a list of seats and returns a hold ID that expires after about ten minutes. A third confirms the booking with that hold ID, the payment details and an idempotency key, so a retried request never charges twice. The main tables are events, seats, holds and bookings. Each seat row has the event ID, a seat label, a status, and the hold it belongs to with an expiry time. Booking must never double-sell, so this lives in a relational database with transactions. To hold seats I run one conditional update that only touches seats that are free or whose hold has expired, and I check that the number of rows changed matches the number of seats asked for. If it doesn't, someone got there first and I roll back. The seat map can come from a cache a few seconds stale, because the hold is the real check."

Code:
BEGIN;
UPDATE seats
SET status = 'held', hold_id = 'h-913', held_until = now() + interval '10 minutes'
WHERE event_id = 42
  AND seat_label IN ('14C', '14D')
  AND (status = 'available' OR (status = 'held' AND held_until < now()));
-- if fewer than 2 rows changed, someone else got a seat first: ROLLBACK
COMMIT;
Red flag to avoid:

Drawing servers before naming a single API call, or modelling seats so that two users can end up booking the same one.

They may ask next:
  • Why hold seats first instead of booking them in a single call?
  • How would this change for a concert where a huge crowd tries to book in the first minute?
Say it in 60 seconds
Medium System design round Fresher, Mid-level, Senior Practice question

4. Estimate the requests per second and the storage for a photo-sharing app with 10 million daily active users. Talk me through the numbers.

What the interviewer is really testing:
Whether you can make sensible assumptions, do round-number arithmetic out loud, and use the result to make a design decision rather than just produce a figure.
Answer frame:

Assumptions: state them first: uploads and views per user per day, average photo size.

Rates: divide daily totals by about 100,000 seconds, then allow for a peak a few times the average.

Storage and bandwidth: multiply out per day and per year, including replicas.

So what: say what the numbers change in the design.

Sample spoken answer:

"I'll assume each user uploads one photo a day at about 200 kilobytes after compression, and views about 100 photos a day. A day is roughly 86,400 seconds, so I'll round to 100,000 to keep the maths easy. Ten million uploads a day is about 100 uploads a second, maybe 300 at peak. Storage is 10 million times 200 kilobytes, so 2 terabytes a day, around 730 terabytes a year, and over 2 petabytes once we keep three copies. Views are a billion a day, so about 10,000 reads a second, and at 200 kilobytes each that's roughly 2 gigabytes a second going out. So what does that tell me? Writes are easy; this is a read-heavy system dominated by image bandwidth. Images belong in object storage behind a CDN, and the metadata database mostly needs caching, not heavy sharding on day one."

Code:
Uploads:  10M users x 1 photo/day   = 10M photos/day
          10M / ~100,000 s          = ~100 uploads/s (peak ~300/s)
Storage:  10M x 200 KB              = 2 TB/day
          2 TB x 365                = ~730 TB/year (x3 copies = ~2.2 PB)
Views:    10M users x 100 views/day = 1B views/day
          1B / ~100,000 s           = ~10,000 reads/s
Egress:   10,000/s x 200 KB         = ~2 GB/s
Red flag to avoid:

Producing numbers with no stated assumptions, or doing careful arithmetic and then never using the result to decide anything.

They may ask next:
  • How would the design change if users uploaded short videos instead of photos?
  • How do you pick the peak-to-average ratio when you have no data?
Say it in 60 seconds

Scaling & Load Balancing 2 questions

Easy Technical round Fresher, Mid-level Practice question

5. What's the difference between scaling vertically and horizontally? What has to change in an app before you can run many copies of it?

What the interviewer is really testing:
Whether you know both options have a place, and whether you understand that horizontal scaling only works once the app servers hold no state of their own.
Answer frame:

Vertical: a bigger machine. Simple, no code change, but there's a ceiling and it's still one point of failure.

Horizontal: more machines behind a load balancer. Near-unlimited and fault tolerant, but the app must be stateless.

Moving state out: sessions, uploads, in-memory counters and scheduled jobs all need a shared home.

Sample spoken answer:

"Scaling vertically means giving one machine more CPU, memory or faster disks. It needs no code changes, which is why I'd often do it first, especially for a database, but there's a hard ceiling and the box is still a single point of failure. Scaling horizontally means running many copies behind a load balancer, which removes the ceiling and survives a machine dying. The catch is that any request may land on any copy, so the servers can't keep state of their own. Sessions move to a shared store or into signed tokens, uploaded files go to object storage instead of local disk, in-memory counters and caches move to a shared cache, and scheduled jobs need a lock or a single scheduler so they don't run once per server. Stateless app servers are easy to scale out; the database is usually the harder part."

Red flag to avoid:

Saying horizontal scaling is always better, or missing that local sessions and files break as soon as there is a second server.

They may ask next:
  • Why are databases so much harder to scale horizontally than web servers?
  • Are sticky sessions a good way to avoid moving session state out? What do they cost you?
Say it in 60 seconds
Easy Technical round Fresher, Mid-level Practice question

6. What does a load balancer actually do? How would you choose between round robin, least connections and hashing?

What the interviewer is really testing:
Whether you understand health checks and routing choices well enough to pick a strategy for a real workload, and remember the balancer can fail too.
Answer frame:

Job: spread traffic, drop unhealthy servers via health checks, let you add or remove servers invisibly.

Algorithms: round robin for similar short requests, least connections for uneven ones, hashing for affinity.

Layer 4 vs 7: route on IP and port, or read HTTP to route by path and terminate TLS.

Redundancy: the balancer itself must not be a single point of failure.

Sample spoken answer:

"A load balancer sits in front of a pool of servers and spreads requests across them. It runs health checks and stops sending traffic to a server that fails them, which is what lets me deploy or add servers without clients noticing. Round robin is fine when requests are short and similar. Least connections is better when some requests are long, like uploads or streaming, because new work goes to the least busy server. Hashing on something like the user ID sends the same user to the same server, which helps if servers keep a local cache, but a few hot keys can overload one machine. There's also the layer: a layer 4 balancer routes on IP and port and is very fast, while a layer 7 balancer reads the HTTP request, so it can route by path and terminate TLS. And the balancer itself runs as a redundant pair or a managed service."

Red flag to avoid:

Describing the load balancer as a magic box that makes things scale, with no mention of health checks or of the balancer being a failure point itself.

They may ask next:
  • What should a health check endpoint actually check, and what goes wrong if it checks too much?
  • How would you drain a server before taking it out for a deploy?
Say it in 60 seconds

Caching 2 questions

Medium Technical round Fresher, Mid-level, Senior Practice question

7. Compare cache-aside, write-through and write-back caching. Which would you pick for a product catalogue, and why?

What the interviewer is really testing:
Whether you know how each pattern behaves on reads, writes and failures, and can match one to a workload instead of reciting definitions.
Answer frame:

Cache-aside: app reads cache, loads from the database on a miss, deletes the key on write.

Write-through: every write updates cache and database together; fresh but slower writes.

Write-back: write to cache, flush to the database later; fast, but data can be lost.

Choice: read-heavy data that can be a little stale suits cache-aside with a TTL.

Sample spoken answer:

"With cache-aside, the application checks the cache first. On a miss it reads the database, stores the result in the cache with a TTL and returns it. On a write it updates the database and deletes the cache key, so the next read reloads a fresh copy. Write-through sends every write to the cache and the database together, so the cache is always warm, but every write pays for both. Write-back writes only to the cache and flushes to the database later, which makes writes very fast but loses data if the cache node dies before it flushes. A product catalogue is read far more often than it changes, and a few seconds of staleness is fine, so I'd use cache-aside with a TTL and delete on update. I delete rather than overwrite, because two writers racing to set the cache can leave the older value behind."

Red flag to avoid:

Recommending write-back for data that must not be lost, or never mentioning how the cache gets invalidated when the data changes.

They may ask next:
  • Even with delete-on-write, how can a stale value still end up in the cache?
  • How would you choose the TTL for prices versus product descriptions?
  • What eviction policy would you use, and what happens when the cache is full?
Say it in 60 seconds
Hard Technical round Mid-level, Senior Practice question

8. A very popular cache key expires and the database collapses under thousands of identical queries at once. What happened, and how do you stop it happening again?

What the interviewer is really testing:
Whether you recognise a cache stampede and know several layered fixes, showing you've thought about caches failing, not just caches working.
Answer frame:

Cause: every request misses at the same instant and each one rebuilds the value from the database.

Coalesce: let one request rebuild while the others wait for it or get the old value.

Serve stale: keep the old value past its soft expiry and refresh it in the background.

Spread expiry: add random jitter to TTLs so many keys don't expire together.

Sample spoken answer:

"That's a cache stampede. While the key was cached, the database never saw those reads. The moment it expired, every request missed together, and each one ran the same expensive query to rebuild the value, so the database got the full traffic in one spike. The main fix is request coalescing: the first request that misses takes a short lock and rebuilds the value, and the others either wait briefly for it or get the previous value. Even better is serving stale data: I store the value with a soft expiry and a longer hard expiry, so after the soft one passes, requests keep getting the old value while one background job refreshes it. I'd also add random jitter to TTLs so keys written together don't all expire together, and for a handful of known hot keys I'd refresh them on a schedule so they never expire at all."

Red flag to avoid:

Suggesting a longer TTL or a bigger database as the fix, without addressing the many simultaneous rebuilds.

They may ask next:
  • What happens to the waiting requests if the one rebuilding the value crashes while holding the lock?
  • How would you find out which keys are hot before they cause an incident?
Say it in 60 seconds

Data Storage 6 questions

Medium Technical round Mid-level, Senior Practice question

9. A user edits their profile, refreshes the page and sees the old values. You run one primary database with read replicas. What's going on, and how do you fix it?

What the interviewer is really testing:
Whether you understand asynchronous replication lag and know practical ways to give users read-your-writes without sending every read to the primary.
Answer frame:

Cause: replication is asynchronous, so the replica that served the refresh hadn't applied the write yet.

Read your writes: send a user's reads to the primary for a short window after they write, or wait for a replica that has caught up.

Consistency per user: pin a user to one replica so they never see time go backwards.

Watch it: monitor lag and pull badly lagging replicas out of rotation.

Sample spoken answer:

"The write went to the primary, but replicas apply changes asynchronously, usually a fraction of a second behind and sometimes much more under load. The refresh hit a replica that hadn't caught up yet, so it returned the old row. Making replication synchronous would fix it but slow every write and tie the primary to the replicas' health. Instead I'd give that user read-your-writes. The simplest version is to route a user's reads to the primary for a short window after they write, say by setting a timestamp in their session. A more precise version records the log position of the write and only reads from a replica that has replayed past it. I'd also pin each user to one replica, so a second refresh doesn't land on a replica that's even further behind. And I'd alert on replication lag and take a replica out of rotation if it falls too far back."

Red flag to avoid:

Blaming the browser cache, or fixing it by sending every read to the primary and throwing away the replicas.

They may ask next:
  • What can you lose if the primary dies and a lagging replica is promoted?
  • How would this problem look for a second user viewing the first user's profile, and does it matter?
Say it in 60 seconds
Hard Technical round Mid-level, Senior Practice question

10. How does leader-follower replication work, and what do you trade between synchronous and asynchronous followers when the leader fails?

What the interviewer is really testing:
Whether you understand what an acknowledged write really guarantees under each replication mode, and the risks of failover such as lost writes and two leaders at once.
Answer frame:

Basics: one leader takes writes; followers replay its change log in the same order and can serve reads.

Sync vs async: a synchronous follower has every acknowledged write but slows writes; asynchronous is fast but can lose recent writes on failover.

Middle ground: one synchronous follower, the rest asynchronous.

Failover: detect the dead leader, promote the most up-to-date follower, and fence the old leader so it can't keep taking writes.

Sample spoken answer:

"All writes go to one leader. It records each change in its log, and followers replay that log in the same order, so they hold the same data and can serve reads. The big choice is when the leader tells the client a write succeeded. With a synchronous follower it waits for that follower to confirm, so if the leader dies, that follower has every acknowledged write, but each write is slower and a stuck follower can stall writes. With asynchronous followers the leader confirms straight away, which is fast, but writes the followers hadn't received are lost when one is promoted. A common middle ground is one synchronous follower and the rest asynchronous. Failover itself is risky. You detect the dead leader with a timeout, promote the most up-to-date follower and repoint clients. Then you must stop the old leader coming back and still accepting writes, which is split brain. I'd use fencing, like an increasing epoch number that rejects writes from an old leader."

Red flag to avoid:

Saying followers are always an exact copy of the leader, or promoting a follower automatically with no thought for lost writes or the old leader returning.

They may ask next:
  • How do you pick the failover timeout, and what goes wrong if it's too short?
  • When would you choose multi-leader or leaderless replication instead?
Say it in 60 seconds
Medium Technical round Mid-level, Senior Practice question

11. The orders table no longer fits comfortably on one database server. How would you shard it, and how do you choose the shard key?

What the interviewer is really testing:
Whether you treat sharding as a last resort with real costs, and pick a key based on access patterns, even distribution and future resharding.
Answer frame:

First: rule out cheaper fixes like indexes, archiving old rows, read replicas and a bigger machine.

Key: follow the main query pattern and spread load evenly; customer ID keeps a customer's orders together.

Costs: cross-shard queries, joins and transactions get hard; reports move to a separate store.

Resharding: use many logical shards mapped onto fewer servers, so growth means moving whole shards.

Sample spoken answer:

"Before sharding I'd check the cheaper options: missing indexes, archiving old orders, read replicas and a bigger machine, because sharding makes everything after it harder. If we still need it, I choose the key from the main access pattern. Most order queries are 'show this customer's orders', so I'd shard by a hash of the customer ID. That keeps one customer's orders on one shard and spreads customers evenly. A range key like order date would be worse, because all new writes would pile onto the newest shard. To look up an order by its own ID, I'd embed the shard number in the order ID. Queries across all customers, like daily sales reports, shouldn't hit the shards at all; they go to an analytics store fed from the shards. For growth, I'd create many logical shards, say a thousand, mapped onto a few servers, so adding capacity means moving whole logical shards instead of rehashing every row."

Red flag to avoid:

Sharding by an auto-increment ID or a timestamp without noticing the hot spot, or never mentioning what happens to cross-shard queries.

They may ask next:
  • One huge business customer places a large share of all orders. What does that do to your scheme?
  • How would you move a logical shard to a new server without downtime?
Say it in 60 seconds
Medium Technical round Mid-level, Senior Practice question

12. What is consistent hashing, and why is it better than hash of the key mod N when you add or remove cache servers?

What the interviewer is really testing:
Whether you understand why naive modulo placement reshuffles almost everything on a resize, and how a hash ring with virtual nodes limits the damage.
Answer frame:

Problem with mod N: changing N changes where most keys map, so most cache entries become misses.

Ring: servers and keys hash onto the same circle; a key belongs to the next server clockwise.

Resize: adding or removing a server only moves the keys next to it, about one Nth of them.

Virtual nodes: each server gets many points on the ring for an even spread.

Sample spoken answer:

"With hash mod N, the server for a key depends on N, so going from four cache servers to five changes the answer for most keys. In fact only about one key in five stays put, so the cache suddenly misses almost everything and the database takes the full load. Consistent hashing puts both servers and keys on the same hash ring. A key belongs to the first server you meet going clockwise from its position. If I add a fifth server, it only takes over the keys between itself and its neighbour, roughly a fifth of them, and everything else stays where it was. Removing a server hands its keys to the next one along. With just one point per server the spread is uneven, so each server gets many virtual nodes on the ring, which evens out the load and lets a bigger machine take more points."

Code:
import bisect, hashlib

def h(key):
    return int(hashlib.md5(key.encode()).hexdigest(), 16)

class Ring:
    def __init__(self, nodes, vnodes=100):
        self.points = sorted((h(f"{n}#{i}"), n) for n in nodes for i in range(vnodes))
        self.hashes = [p for p, _ in self.points]

    def node_for(self, key):
        i = bisect.bisect(self.hashes, h(key)) % len(self.hashes)
        return self.points[i][1]

ring = Ring(["cache-a", "cache-b", "cache-c"])
print(ring.node_for("user:42"))
Red flag to avoid:

Claiming consistent hashing balances load perfectly on its own, or not being able to say which keys move when a server is added.

They may ask next:
  • Where else besides caches have you seen consistent hashing used?
  • If one key is extremely hot, does consistent hashing help at all?
Say it in 60 seconds
Medium Technical round Mid-level, Senior Practice question

13. Explain strong consistency, eventual consistency and read-your-writes. For one app, give me a feature that needs each.

What the interviewer is really testing:
Whether you can match a consistency level to each feature based on what a stale read would cost, instead of demanding the strongest guarantee everywhere.
Answer frame:

Strong: every read sees the latest committed write, as if there were one copy. Costs latency and availability.

Eventual: replicas converge if writes stop; reads may be stale for a while.

Read-your-writes: a user always sees their own changes, even if others see them a bit later.

Per feature: decide by the cost of a stale read.

Sample spoken answer:

"Strong consistency means every read sees the most recent committed write, as if there were only one copy of the data. Eventual consistency means replicas may disagree for a while, but if writes stop they all converge on the same value. Read-your-writes sits in between: a user always sees their own changes, even if other users see them slightly later. Take a ticket booking app. Seat reservation needs strong consistency, because two people must never both get seat 14C. The count of people who viewed an event can be eventually consistent; if it's a few seconds behind, nobody is harmed and it's much cheaper to scale. Reviews need read-your-writes: when I post a review and the page reloads, I must see it, or I'll post it again, but it's fine if another visitor sees it a second later. I pick per feature by asking what a stale read would actually cost."

Red flag to avoid:

Saying eventual consistency means data might never become correct, or insisting on strong consistency for everything without mentioning its cost.

They may ask next:
  • What's causal consistency, and in a comments thread why might users care about it?
  • How would you give read-your-writes on top of an eventually consistent store?
Say it in 60 seconds
Medium Technical round Mid-level, Senior Practice question

14. What does the CAP theorem actually say, and how would it change a decision in a design you're building?

What the interviewer is really testing:
Whether you know CAP is about behaviour during a network partition rather than a pick-two menu, and can apply it feature by feature.
Answer frame:

Statement: during a network partition a replicated store must choose between consistency and availability.

Not pick two: partitions happen in real networks, so the real choice is C or A while partitioned.

Normal times: without a partition the trade-off is latency against consistency.

Apply it: choose per feature, by which failure hurts the business less.

Sample spoken answer:

"CAP is about what happens during a network partition, when some nodes can't reach others. In that moment a replicated store has two options. It can refuse requests it can't confirm, so nobody sees stale or conflicting data, which is choosing consistency. Or it can keep answering on both sides and reconcile later, which is choosing availability. The popular 'pick two of three' framing is misleading, because you can't opt out of partitions in a real network. It also says nothing about normal operation, where the everyday trade-off is latency against consistency. In a design I apply it per feature. A shopping cart can stay writable on both sides and merge later, because losing a sale is worse than a duplicate item the user removes. A seat booking or an account balance should reject writes it can't confirm, because an error message is better than selling the same seat twice."

Red flag to avoid:

Reciting 'you can only have two of the three' and labelling databases CA, without explaining what actually happens during a partition.

They may ask next:
  • How would you merge two versions of a shopping cart that were edited on both sides of a partition?
  • Is a single-node relational database CP or AP?
Say it in 60 seconds

Messaging 3 questions

Easy Technical round Fresher, Mid-level Practice question

15. Why would you put a message queue between two services? Give me one case where it clearly helps and one where it just adds trouble.

What the interviewer is really testing:
Whether you understand what asynchronous messaging buys you and what it costs, rather than adding a queue to every diagram by reflex.
Answer frame:

Benefits: decoupling, absorbing spikes, retrying failed work, letting slow tasks run out of the request.

Good fit: follow-up work after an order, like email, invoice and analytics.

Bad fit: when the caller needs the answer right now to continue.

Costs: eventual consistency, harder debugging, one more system to run.

Sample spoken answer:

"A queue lets a service hand off work without waiting for it to finish or even for the other service to be up. Messages wait until a consumer is ready, so a traffic spike becomes a longer queue instead of an outage, and failed work can be retried. A clear win is placing an order. The checkout service saves the order and publishes one message, and separate consumers send the confirmation email, generate the invoice and update analytics. Checkout stays fast, and if the email provider is down the emails just go out later. It's the wrong tool when the caller needs the answer to carry on, like checking a password or getting a price quote. Pushing that through a queue means inventing a reply channel and timeouts for what should be a simple request. And every queue brings eventual consistency, harder tracing and another system to monitor, so I add one when there's a real reason."

Red flag to avoid:

Adding a queue between every pair of services 'for scalability' with no mention of eventual consistency or the operational cost.

They may ask next:
  • What's the difference between a work queue and publish-subscribe, and when do you need each?
  • How do you notice that consumers are falling behind?
Say it in 60 seconds
Medium Technical round Mid-level, Senior Practice question

16. Most queues promise at-least-once delivery. What does that mean for the consumer, and how do you make processing a message safe to repeat?

What the interviewer is really testing:
Whether you know duplicates are normal, not a bug, and can design consumers so a repeated message has no extra effect.
Answer frame:

Meaning: a message may be delivered more than once, for example when a consumer crashes before acknowledging.

Idempotent consumer: record each message ID in the same transaction as the effect, and skip IDs already seen.

Natural idempotency: prefer 'set status to shipped' over 'add one' where you can.

Poison messages: cap retries and move repeat failures to a dead-letter queue.

Sample spoken answer:

"At-least-once means the broker keeps redelivering until the consumer acknowledges. If my consumer does the work and then crashes before it acks, the same message comes back. So duplicates are a normal event, and the consumer has to make repeats harmless. Where I can, I make the operation naturally idempotent, like setting an order's status to shipped rather than incrementing a counter. When I can't, I keep a processed-messages table with the message ID as the primary key, and insert into it in the same database transaction as the real change. If the insert fails because the ID already exists, I know it's a duplicate, roll back and just acknowledge. I only ack after the transaction commits. And if one message keeps failing, I stop retrying after a few attempts and move it to a dead-letter queue so it doesn't block everything behind it."

Code:
BEGIN;
-- message_id is the primary key, so a duplicate makes this insert fail
INSERT INTO processed_messages (message_id) VALUES ('msg-8841');
UPDATE accounts SET balance = balance + 50 WHERE id = 7;
COMMIT;
Red flag to avoid:

Assuming each message arrives exactly once, or acknowledging the message before the work is safely committed.

They may ask next:
  • How long do you keep processed message IDs, and what happens if you delete them too soon?
  • Some brokers advertise exactly-once. What does that really cover?
Say it in 60 seconds
Hard Technical round Mid-level, Senior Practice question

17. Your service saves an order to the database and then publishes an 'order created' event. Now and then the event never arrives. Why, and how do you fix it?

What the interviewer is really testing:
Whether you spot the dual-write problem and know the outbox pattern, which is how real systems keep a database and a message stream in step.
Answer frame:

Cause: two separate writes with no shared transaction; a crash or error between them loses the event.

Wrong fixes: publishing first can announce an order that then fails to save.

Outbox: write the event into an outbox table in the same transaction as the order.

Relay: a separate process publishes outbox rows, so delivery is at least once and consumers stay idempotent.

Sample spoken answer:

"It's a dual write. Saving the order and publishing the event are two separate operations with no shared transaction. If the process crashes, gets redeployed or the broker call fails after the commit, the order exists but the event is gone. Swapping the order doesn't help: publish first and a failed save leaves consumers acting on an order that doesn't exist. The fix I'd use is a transactional outbox. In the same database transaction that inserts the order, I insert a row into an outbox table describing the event. Either both are saved or neither is. Then a separate relay reads unsent outbox rows, publishes them and marks them sent, either by polling or by reading the database's change log. If the relay crashes after publishing but before marking a row, it will publish that event again, so delivery is at least once and consumers must be idempotent. I'd also clean up old sent rows."

Red flag to avoid:

Suggesting a retry loop around the publish call, or a distributed transaction across the database and the broker, as if either closes the gap.

They may ask next:
  • How do you keep events for the same order in the right sequence when the relay runs on several machines?
  • What are the pros and cons of polling the outbox table versus reading the database's change log?
Say it in 60 seconds

Classic Designs 7 questions

Medium System design round Mid-level, Senior Practice question

18. Design a rate limiter that allows each API key a fixed number of requests per minute, enforced across a fleet of servers. Which algorithm, and where does the state live?

What the interviewer is really testing:
Whether you can compare limiting algorithms, keep shared counters correct under concurrency, and decide how the limiter behaves when its own store fails.
Answer frame:

Algorithm: token bucket allows short bursts while holding the average; fixed windows leak bursts at the boundary.

Shared state: counters live in a fast shared store, updated atomically.

Placement: at the gateway or in middleware, returning 429 with a Retry-After header.

Failure mode: decide fail open or fail closed per endpoint.

Sample spoken answer:

"I'd use a token bucket per API key. Each bucket holds up to a set number of tokens and refills at a steady rate; each request spends one, and an empty bucket means the request is rejected with a 429 and a Retry-After header. It allows short bursts but holds the average. A fixed window counter is simpler, but a client can send double the limit by clustering requests around a window boundary, and a sliding log is exact but stores every timestamp. With many servers, the state can't live in each server's memory, so I'd keep it in a shared in-memory store and do the read-refill-spend step as one atomic operation, so two servers can't both spend the last token. The limiter lives in the gateway so every service gets it. If the store goes down, I'd fail open for normal endpoints and fail closed for sensitive ones like login."

Code:
import time

class TokenBucket:
    def __init__(self, capacity, refill_per_sec):
        self.capacity = capacity
        self.rate = refill_per_sec
        self.tokens = capacity
        self.last = time.monotonic()

    def allow(self):
        now = time.monotonic()
        self.tokens = min(self.capacity, self.tokens + (now - self.last) * self.rate)
        self.last = now
        if self.tokens >= 1:
            self.tokens -= 1
            return True
        return False

bucket = TokenBucket(capacity=10, refill_per_sec=5)
print(bucket.allow())
Red flag to avoid:

Keeping counters in each server's memory behind a load balancer, or doing a separate read and write so concurrent requests overspend the limit.

They may ask next:
  • Calling the shared store on every request adds latency. How could you cut that down, and what accuracy do you give up?
  • How would you give paying customers higher limits without a code change?
Say it in 60 seconds
Medium System design round Fresher, Mid-level, Senior Practice question

19. Design a URL shortener. Walk me through the estimates, how you generate the short code, and what happens when someone clicks a short link.

What the interviewer is really testing:
Whether you can run a full small design: estimate load, choose a collision-free key scheme, and make the read path fast, with a clear view of the redirect trade-off.
Answer frame:

Estimates: writes and reads per second, total links over the retention period, storage.

Code generation: unique ID from a counter service, encoded in base 62.

Read path: cache in front of a key-value store; redirect with 302 or 301.

Extras: expiry, custom aliases, abuse checks, guessability.

Sample spoken answer:

"Say 100 million new links a month and a hundred redirects per new link. A month is about 2.6 million seconds, so that's roughly 40 writes and 4,000 redirects a second. Over five years it's 6 billion links, and at about 500 bytes each, around 3 terabytes, which fits easily in a sharded key-value store. For the code, a counter service hands each app server a block of IDs, so there are no collisions and no coordination per request, and I encode the ID in base 62. Seven characters give about 3.5 trillion codes, far more than we need. On a click I look up the code, cache first because popular links are very hot, and return a 302 so every click reaches us for analytics. A 301 gets cached by browsers, which cuts load but hides repeat clicks. Sequential codes are guessable, so for private links I'd scramble the ID before encoding."

Code:
ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

def to_base62(n):
    if n == 0:
        return ALPHABET[0]
    out = []
    while n:
        n, r = divmod(n, 62)
        out.append(ALPHABET[r])
    return "".join(reversed(out))

print(to_base62(125))  # "21"
Red flag to avoid:

Generating random codes and checking the database for collisions on every write without noticing the cost, or never doing the estimates.

They may ask next:
  • Why not just hash the long URL and take the first seven characters?
  • How would you handle a user asking for a custom alias that's already taken?
  • How do you stop the service being used to hide phishing links?
Say it in 60 seconds
Hard System design round Mid-level, Senior Practice question

20. Design the home feed for a social app where users follow each other. Do you build a user's feed when someone posts, or when the user opens the app?

What the interviewer is really testing:
Whether you understand fan-out on write versus fan-out on read, spot the celebrity problem, and land on a hybrid with sensible storage and paging.
Answer frame:

Fan-out on write: on each post, push its ID into every follower's feed list. Fast reads, costly for huge accounts.

Fan-out on read: on open, pull recent posts from everyone followed and merge. Cheap writes, slow reads.

Hybrid: push for normal accounts, pull for very large ones at read time, then merge.

Details: store only post IDs, cap list length, hydrate from a post cache, page with a cursor.

Sample spoken answer:

"There are two approaches. Fan-out on write means that when someone posts, a background worker pushes the post ID into a cached feed list for each follower, so opening the app is just reading one list. That's great for reads, but an account with tens of millions of followers turns one post into tens of millions of writes. Fan-out on read means building the feed when the user opens the app, by fetching recent posts from everyone they follow and merging them. Writes are cheap, but reads are slow for someone following thousands of accounts. So I'd go hybrid. Normal accounts fan out on write. Very large accounts are skipped at write time, and their recent posts are pulled and merged in when a follower reads. Feed lists hold only post IDs and are capped at a few hundred, the post content comes from a separate cache, and paging uses a cursor. I'd also skip precomputing feeds for inactive users."

Red flag to avoid:

Picking pure fan-out on write without noticing accounts with millions of followers, or storing full post bodies in every follower's feed.

They may ask next:
  • How would ranking change this design compared with a simple newest-first feed?
  • A user unfollows someone. How do their posts leave the precomputed feed?
  • What happens to the fan-out workers when a large account posts during peak hours?
Say it in 60 seconds
Hard System design round Mid-level, Senior Practice question

21. Design a chat system with one-to-one and group chats. How does a message reach someone who's online right now, and someone who's offline?

What the interviewer is really testing:
Whether you can handle long-lived connections, message ordering, delivery guarantees and offline users, which is where chat designs usually fall apart.
Answer frame:

Connections: clients hold a WebSocket to a gateway server; a registry maps each user to their gateway.

Send path: chat service assigns a per-conversation sequence number, stores the message, then routes it.

Offline: send a push notification; on reconnect the client syncs everything after its last sequence number.

Reliability: client-generated message IDs for dedupe, acks for sent, delivered and read.

Sample spoken answer:

"Each client keeps a WebSocket open to one of many gateway servers, and a registry records which gateway each online user is connected to. When I send a message, it carries an ID my client generated, so retries don't create duplicates. The chat service gives it the next sequence number for that conversation, stores it in a store partitioned by conversation ID and ordered by sequence, and only then acks back to me. Then it looks up the recipient in the registry. If they're online, their gateway pushes the message and their client acks delivery. If they're offline, we send a push notification, and when they reconnect the client asks for everything after the last sequence number it has, so nothing is lost even if a push was missed. Groups work the same way with fan-out to each member, and very large groups switch to members pulling. Presence comes from heartbeats and is allowed to be a little stale."

Red flag to avoid:

Having clients poll the server every second for new messages, or ordering messages by client timestamps.

They may ask next:
  • A gateway server crashes with thousands of connections on it. What happens to those users and their in-flight messages?
  • How would you add end-to-end encryption, and what does the server lose the ability to do?
  • How do you keep message order correct when a user sends from two devices at once?
Say it in 60 seconds
Medium System design round Mid-level, Senior Practice question

22. Design a notification service other teams call to send push, email and SMS. How do you make sure users don't get the same message twice, or one at 3 a.m.?

What the interviewer is really testing:
Whether you can build a shared platform with preferences, priorities, retries and deduplication, not just a loop that calls an email provider.
Answer frame:

Intake: one API with an idempotency key, the user, a template and a priority.

Rules: check opt-outs and channel preferences, quiet hours in the user's time zone, and per-user caps.

Delivery: separate queues per channel and priority; workers call providers with backoff and a dead-letter queue.

Tracking: record the status of each send so teams can see what happened.

Sample spoken answer:

"Teams call one API with the user, a template name, data and an idempotency key. The service first checks that key in a dedupe store, so a caller retrying after a timeout doesn't cause a second send. Then it applies rules: the user's opt-outs and channel preferences, quiet hours in the user's own time zone, and a cap on how many notifications one user gets in a day. Anything that shouldn't go now is scheduled for later or dropped. It renders the template and puts the message on a queue for that channel. I'd keep urgent traffic, like login codes, on separate queues from marketing, so a huge campaign never delays someone signing in. Workers call the push, email or SMS providers, retry with exponential backoff, and move repeated failures to a dead-letter queue. Every send gets a status record, so a team can see whether a message was sent, skipped or failed, and why."

Red flag to avoid:

Sending straight from the API request to the provider with no queue, or having no answer for retries producing duplicate messages.

They may ask next:
  • One email provider starts failing. How would the service switch to another without sending duplicates?
  • How do you stop a buggy caller from sending the same user fifty messages in a minute?
Say it in 60 seconds
Hard System design round Mid-level, Senior Practice question

23. Design a file storage and sync service where people edit files on several devices. How do you upload large files and keep every device in sync?

What the interviewer is really testing:
Whether you separate file content from metadata, use chunking for resumable and incremental uploads, and have a real answer for sync and conflicts.
Answer frame:

Chunks: split files into chunks identified by content hash; upload only the ones the server lacks.

Storage split: chunks in object storage, file metadata and versions in a database.

Sync: a per-user change log with a cursor; devices fetch changes since their cursor when notified.

Conflicts: if two devices edit the same version, keep both and create a conflicted copy.

Sample spoken answer:

"I'd split every file into chunks of a few megabytes and identify each chunk by a hash of its content. Before uploading, the client asks which hashes the server already has, and only sends the missing ones. That gives resumable uploads, deduplication, and cheap edits, because changing one part of a big file only re-uploads the chunks that changed. Chunks go straight to object storage through short-lived signed URLs, so file bytes never pass through my app servers. The metadata service stores each file as an ordered list of chunk hashes, with versions, in a relational database. Every change is appended to a per-user change log with an increasing cursor. Other devices get a lightweight notification, then ask for all changes after their last cursor and download only the chunks they're missing. If two devices edit from the same version, the first commit wins and the second is saved as a conflicted copy, so no one's work is silently lost."

Red flag to avoid:

Uploading whole files through the app servers on every save, or letting the last writer silently overwrite another device's changes.

They may ask next:
  • A device has been offline for a month. How does it catch up without downloading everything again?
  • How would you share a folder between two users in this model?
  • When a user deletes a file, when can you safely delete its chunks?
Say it in 60 seconds
Hard System design round Mid-level, Senior Practice question

24. Design search autocomplete that suggests popular queries as the user types each letter. How do you make it fast enough to keep up with typing?

What the interviewer is really testing:
Whether you separate the offline work of ranking suggestions from the tiny, very frequent lookups, and use caching on the client and at the edge.
Answer frame:

Offline: aggregate query logs over a time window and compute the top suggestions for every prefix.

Serving: a prefix table or trie with the top results stored at each node, held in memory and replicated.

Client and edge: debounce keystrokes, cache prefixes in the browser and at a CDN.

Freshness and safety: periodic rebuilds, a faster path for trending terms, filtering of unwanted suggestions.

Sample spoken answer:

"The key is to do the heavy work offline. A batch job reads the query logs for a recent window, counts how often each query was searched, and builds a map from every prefix to its top ten or so completions, which is really a trie with the top results precomputed at each node. At request time, a lookup is just 'give me the list stored for this prefix', so it's served from memory in well under the time between keystrokes. The data is replicated across servers and can be split by prefix if it grows. On the client I debounce, so fast typing doesn't send a request per letter, and cache results in the browser. Short prefixes are the same for everyone, so they can be cached at a CDN too. The full rebuild runs on a schedule, a small streaming job boosts terms trending right now, and a filter removes offensive or unwanted suggestions before anything is published."

Red flag to avoid:

Running a prefix-matching LIKE query against the main database on every keystroke, or ranking suggestions live at request time.

They may ask next:
  • How would you add personal suggestions from the user's own history without slowing the lookup down?
  • How do you handle users who make a typo in the prefix?
Say it in 60 seconds

Reliability & Observability 2 questions

Easy Technical round Fresher, Mid-level, Senior Practice question

25. What's the difference between logs, metrics and traces? When latency suddenly goes up in production, which do you look at first?

What the interviewer is really testing:
Whether you know what each signal is good at and can use them in a sensible order to go from 'something is slow' to the exact cause.
Answer frame:

Metrics: cheap numbers over time, like request rate, errors and latency percentiles. Used for alerts and dashboards.

Traces: the path of one request across services, with timing for each step.

Logs: detailed events, structured and tagged with a request ID so they join up with traces.

Order: metrics to find where and when, traces to find the slow step, logs for the exact detail.

Sample spoken answer:

"Metrics are numbers aggregated over time, like requests per second, error rate and latency percentiles per endpoint. They're cheap to keep, so they drive dashboards and alerts. Traces follow one request through every service it touches and show how long each step took. Logs are detailed events, and they're most useful when they're structured and carry the same request ID as the trace. When latency jumps, I start with metrics: which service, which endpoint, when it started, and whether it lines up with a deploy or a traffic change. I look at the 99th percentile, not the average, because averages hide the slow tail that users actually feel. Then I open traces of slow requests to see which step is eating the time, maybe a database call or a downstream service. Finally I read the logs for that step to find the exact query, error or timeout."

Red flag to avoid:

Starting by grepping raw logs on each server, or judging latency only by the average.

They may ask next:
  • What's the difference between an SLI, an SLO and an SLA?
  • Why is alerting on high CPU usually worse than alerting on what users experience?
Say it in 60 seconds
Medium Technical round Mid-level, Senior Practice question

26. One downstream service slows down and soon your whole system is timing out. How do timeouts, retries and circuit breakers stop that kind of failure from spreading?

What the interviewer is really testing:
Whether you understand how slowness cascades through shared resources, and know that retries can make an outage worse unless they're bounded.
Answer frame:

Cascade: callers hold threads and connections while waiting, run out, and start failing themselves.

Timeouts: every remote call gets one, shorter than the caller's own deadline.

Retries: only for idempotent calls, with exponential backoff, jitter and a small budget.

Circuit breaker: after repeated failures stop calling for a while, fail fast or use a fallback, then probe.

Sample spoken answer:

"A slow dependency is often worse than a dead one. Every caller holds a thread or connection while it waits, the pools fill up, and then the caller can't serve anything, even requests that never touch that dependency. First, every remote call needs a timeout, set shorter than the deadline of whoever is calling me. Retries help with brief blips, but only for idempotent calls, with exponential backoff and random jitter, and a small cap. Without that, retries multiply load on a service that's already struggling, and if three layers each retry three times, one user request becomes dozens of calls. A circuit breaker watches failures, and once they cross a threshold it opens and fails fast, or serves a fallback like cached data, instead of calling at all. After a pause it lets a few trial requests through and closes again if they succeed. I'd also give each dependency its own connection pool, so one slow service can't take them all."

Red flag to avoid:

Adding retries everywhere as the fix without backoff or limits, which turns a slowdown into a retry storm.

They may ask next:
  • How would you pick the timeout value for a call to a service you don't own?
  • What sensible fallback could a product page show if the recommendations service is down?
Say it in 60 seconds

Design Judgement 6 questions

Medium Behavioral round Mid-level, Senior Practice question

27. Tell me about a system you designed or helped design at work. What was the biggest trade-off you made, and would you make it again?

What the interviewer is really testing:
Whether you've made real design decisions under constraints, can explain the alternatives you rejected, and can judge your own call honestly with hindsight.
Answer frame:

Context: what the system did, the load, the team and the deadline.

Decision: the options you weighed and why you picked one.

Outcome: what happened in production, with a concrete result.

Hindsight: what you'd keep, what you'd change and why.

Sample spoken answer:

"At my last company I designed the service that sent order status updates to customers. We had a few weeks and a team of three, and the big decision was whether to use a queue from day one or have the order service call the sender directly. I chose the queue with an outbox table, because the email provider had regular slowdowns and I didn't want checkout waiting on it. It cost us about a week more and a new piece of infrastructure to run. In production it paid off: when the provider had an outage for several hours, messages just queued up and drained afterwards, and checkout never noticed. What I'd change is that I didn't build deduplication at first, and a consumer redeploy sent some customers two emails. I'd design for duplicates from the start now, because with a queue they're a certainty, not an edge case."

Red flag to avoid:

A story where every decision was right, or where you can't name a single alternative you considered.

They may ask next:
  • What would have happened if you'd chosen the simpler option?
  • How did you convince the team the extra week was worth it?
Say it in 60 seconds
Medium Behavioral round Mid-level, Senior Practice question

28. Tell me about a time a system you worked on hit a scaling limit in production. How did you find the bottleneck, and what did you change?

What the interviewer is really testing:
Whether you find bottlenecks with measurement rather than guesses, fix the actual constraint, and verify the result.
Answer frame:

Symptom: what broke, when and how users felt it.

Diagnosis: the metrics, traces or tests that pointed to the real limit.

Fix: the change, and why it addressed the cause rather than the symptom.

Proof: how you confirmed it worked and what you put in place afterwards.

Sample spoken answer:

"At my last company our reporting API started timing out every Monday morning when clients pulled weekly reports. The first instinct on the team was to add more app servers, but the app servers' CPU was low. The database metrics told the story: connections were maxed out and one query dominated the slow query log. Traces showed each report ran the same heavy aggregation over a week of raw events, once per request. Adding servers would only have added more connections fighting over the same database. I moved that aggregation into a job that built a daily summary table overnight, so the report read a few hundred rows instead of millions. Report time dropped from around twenty seconds to under a second, and the Monday spike disappeared from the database graphs. Afterwards I added an alert on connection pool usage, and we put a load test for the Monday pattern into our release checks."

Red flag to avoid:

A story where the fix was adding servers or memory without ever identifying what the actual bottleneck was.

They may ask next:
  • What would you have done if the aggregation needed to be real time?
  • How did you make sure the summary table stayed correct when late events arrived?
Say it in 60 seconds
Easy Behavioral round Fresher, Mid-level, Senior Practice question

29. Tell me about a design review where you disagreed with the proposed architecture. How did you make your case, and what happened?

What the interviewer is really testing:
Whether you can challenge a design with evidence and respect, stay open to being wrong, and commit once a decision is made.
Answer frame:

Concern: what you disagreed with and the specific risk you saw.

Evidence: how you backed it up: numbers, a prototype, a failure scenario.

Outcome: what was decided, including if you didn't get your way.

Relationship: how you worked with the author afterwards.

Sample spoken answer:

"At my last company a senior engineer proposed keeping user sessions in each app server's memory for a new service, to avoid another dependency. My concern was that we'd planned to run several instances behind a load balancer, so users would be logged out whenever a request hit a different server or during every deploy. Instead of arguing in the meeting, I asked for a day, ran two instances locally and recorded a short demo of a user losing their session on the second request. I suggested signed tokens or a small shared session store and wrote down the cost of each. He agreed once he saw it, and we went with the shared store. I made sure to credit his point about fewer dependencies, which is why we picked the simplest managed option."

Red flag to avoid:

A story about winning an argument by seniority or persistence, with no evidence and no respect for the other person's reasoning.

They may ask next:
  • Tell me about a time you pushed back and turned out to be wrong. What did you do?
  • What do you do if the decision goes against you and you still think it's a mistake?
Say it in 60 seconds
Medium Situational round Fresher, Mid-level, Senior Practice question

30. Halfway through your design, the interviewer says traffic just grew ten times. Your database is already the busiest part. What do you do?

What the interviewer is really testing:
Whether you can adapt calmly by finding the new bottleneck with rough numbers and applying the cheapest effective fix first, instead of redrawing everything.
Answer frame:

Re-estimate: redo the load numbers and say which component breaks first.

Reads first: caching and read replicas if the growth is mostly reads.

Then writes: batching, queues to smooth spikes, and sharding only if a single primary can't take the write rate.

Say what changes: name the new trade-offs, like staleness or harder queries.

Sample spoken answer:

"I wouldn't redraw the whole diagram. I'd first redo the numbers out loud. If we were at 2,000 reads and 200 writes a second, we're now at 20,000 and 2,000, and I'd ask whether the growth is mostly reads, since for most products it is. For reads, I'd put a cache in front of the hottest queries and add read replicas, and I'd make sure the app servers are stateless so they scale out behind the balancer. Then writes: 2,000 a second may still fit on one well-tuned primary, but if it doesn't, I'd look at batching writes, moving non-urgent ones behind a queue, and finally sharding by a key that matches the main access pattern. I'd close by naming what we gave up, like slightly stale reads from the cache and replicas, and cross-shard queries getting harder, and ask whether that's acceptable for this product."

Red flag to avoid:

Jumping straight to sharding and microservices without re-estimating or checking whether reads or writes grew.

They may ask next:
  • Which parts of your original design survive a hundred times the traffic unchanged?
  • How would you know in real life, not in an interview, which component breaks first?
Say it in 60 seconds
Medium Situational round Mid-level, Senior Practice question

31. Your team of five wants to split a working monolith into a dozen microservices, and your lead asks for your view. What do you say?

What the interviewer is really testing:
Whether you weigh architecture against team size and real pain points, and know the operational cost of a distributed system, rather than following fashion.
Answer frame:

Find the pain: ask what problem the split is meant to solve.

Costs: network failures, distributed data, deploy and monitoring overhead, split across only five people.

Cheaper options: a modular monolith with clear boundaries, then extract a service only where there's a concrete reason.

Next step: pick the one module with the strongest case and measure the result.

Sample spoken answer:

"I'd start by asking what problem we're trying to solve. If it's slow deploys, tangled code or one part needing to scale differently, each of those has a cheaper fix than a dozen services. For five people, a dozen services means each person owns two or three, each with its own pipeline, monitoring, on-call and data store. Calls that used to be function calls become network calls that can time out, and joins across what used to be one database become distributed data problems. So I'd suggest making the monolith modular first: clear module boundaries, no reaching into another module's tables, and tests that enforce it. Then, if one part has a real reason to stand alone, like a video processing job that needs very different hardware, we extract just that one and see what it costs us to run. If that goes well and the team grows, we'll have a pattern for the next one."

Red flag to avoid:

Agreeing that microservices are always more scalable, or dismissing the idea without asking what problem the team is actually facing.

They may ask next:
  • What signs would convince you that it's now the right time to split out services?
  • How would you split the database when you extract that first service?
Say it in 60 seconds
Hard Situational round Senior Practice question

32. Your main database is close to its limits and a big launch is two weeks away. Sharding would take months. What do you do?

What the interviewer is really testing:
Whether you can triage under a deadline: measure what the load really is, buy headroom with quick safe wins, protect the launch, and plan the longer-term fix separately.
Answer frame:

Measure: find the top queries by total time and whether the pressure is reads, writes, connections or storage.

Quick wins: indexes, query fixes, caching hot reads, read replicas, connection pooling, a bigger instance.

Protect launch: load test the launch pattern, add rate limits and feature flags to shed load.

Long term: start the real scaling plan in parallel, without betting the launch on it.

Sample spoken answer:

"First I'd find out what 'close to its limits' actually means: CPU, disk, connections or storage, and which queries are responsible. Usually a handful of queries account for most of the load, and a missing index or an unbounded query can be fixed in a day. Next I'd buy headroom with low-risk moves: cache the hottest reads, send read-only traffic like reports to a replica, put a connection pooler in front if connections are the issue, and schedule a move to a bigger instance well before launch day. Then I'd protect the launch itself: load test the expected pattern against a copy of production, add rate limits, and put heavy non-essential features behind flags so we can switch them off if the database struggles. Background jobs pause during the launch window. Sharding or moving some data elsewhere becomes a separate project that starts now, but the launch doesn't depend on it."

Red flag to avoid:

Starting an emergency sharding migration two weeks before launch, or doing nothing until the database falls over.

They may ask next:
  • What would you put on the launch-day dashboard, and what number would make you turn features off?
  • Which of these quick fixes carries the most risk, and how would you roll it back?
Say it in 60 seconds
Were you asked something else? Share it A person checks every question before it goes on the site. No name is shown.
For the call itself

The questions above are the prep. The call has ten more.

ClapAssist is an AI interview assistant for Mac and Windows. It listens to the interview on your computer and shows you what to say, in short lines you can read while you talk. Your resume and notes are never stored on our servers. It stays out of screen share on every plan; only you can see it.

Download ClapAssist with 10 free minutes
Mac and Windows · Stays out of screen share · No card