System Design Interview Questions 2026
System design rounds trip people up in a specific way: you can know every individual concept, caching, load balancing, sharding, and still freeze when someone says "design Bit.ly" and hands you a whiteboard. This round isn't really testing whether you've memorized definitions, it's testing whether you can take a vague problem, ask the right questions, and build up a reasonable architecture under time pressure while explaining your tradeoffs out loud.
This page covers both sides of that: the underlying concepts (load balancers, caching strategies, database sharding, message queues) and how those concepts actually get combined when someone asks you to design a real system. If you're prepping for SDE-2 or senior roles, this round usually carries more weight than a single DSA question, so it's worth taking seriously.
Why System Design Rounds Matter So Much
Companies use system design interviews to check something that's hard to test any other way: can you operate at a level above "write a function that passes these test cases." They want to see if you can:
- Break a big, ambiguous problem into components instead of freezing on where to start
- Reason about tradeoffs (consistency vs availability, cost vs performance) instead of picking one "correct" answer
- Estimate scale, back-of-envelope numbers for traffic, storage, and bandwidth, and design accordingly
- Explain your decisions clearly, since in a real job you'll need to justify architecture choices to a team
Who Should Prepare With This Guide
- Backend and full stack engineers interviewing for SDE-2 and above roles
- Anyone who's comfortable with DSA rounds but has never actually sat through a system design interview
- Engineers who've built features inside an existing system but never had to design one from scratch
Related Resources
System Design Interview Questions and Answers (2026)
System Design Fundamentals
1. What's the actual difference between scalability and performance? People tend to conflate these.
Performance is about how fast your system responds under a given load, response time, latency, throughput at a fixed number of users. Scalability is about how well your system holds that performance as load increases. A system can have great performance at 100 users and terrible scalability, meaning the moment you hit 10,000 users it falls over completely, even though it was fast at the smaller scale. Interviewers care more about scalability because that's the part that actually breaks in production.
2. What's the difference between horizontal and vertical scaling, and why do interviewers almost always want you to lean toward horizontal?
Vertical scaling means adding more resources, CPU, RAM, to a single existing machine. Horizontal scaling means adding more machines and distributing the load across them. Vertical scaling is simpler but hits a hard ceiling, there's a maximum size machine you can buy, and it's a single point of failure. Horizontal scaling has effectively no ceiling and gives you redundancy for free, if one machine dies, the others keep serving traffic, which is why almost every large-scale system design leans horizontal, even though it adds real complexity around load balancing and data consistency across nodes.
3. What's the difference between availability and reliability?
Reliability is about whether a system produces correct results consistently over time, no data corruption, no dropped requests, no incorrect responses. Availability is about whether the system is up and responding at all, usually expressed as a percentage like 99.9% uptime ("three nines"). A system can be highly available but not reliable, always responding, but sometimes with wrong data, and the reverse is also possible, correct when it works, but frequently down.
4. What is the CAP theorem, and what does it actually force you to give up?
CAP theorem says a distributed system can only fully guarantee two of three properties at the same time: Consistency (every read gets the most recent write), Availability (every request gets a response, even if it's not the latest data), and Partition tolerance (the system keeps working even if network communication between nodes breaks). Since network partitions are a fact of life in any real distributed system, partition tolerance isn't really optional, so in practice the real choice you're making is between consistency and availability when a partition happens, that's the tradeoff people actually mean when they invoke CAP in an interview.
5. What's the difference between latency and throughput?
Latency is how long a single request takes, start to finish. Throughput is how many requests the system can handle in a given time window. These aren't the same thing and can even trade off against each other, batching requests together can improve throughput while increasing the latency of any individual request, since it now waits for the batch to fill up. A good system design answer usually needs to state which one matters more for the specific problem you're solving.
6. How do you actually approach a system design interview question when they just say "design X"?
Don't jump straight to drawing boxes. A reasonable structure: clarify requirements first (functional, what should it actually do, and non-functional, how many users, read-heavy or write-heavy, how much data), estimate scale with rough back-of-envelope numbers, sketch a high-level architecture (API layer, database, cache, and so on), then go deeper on two or three components the interviewer seems most interested in, discussing tradeoffs as you go instead of presenting one "final" answer. The biggest mistake people make is designing in silence and only talking at the end, interviewers are grading how you think, not just the diagram you land on.
Networking and Communication Basics
1. What is a load balancer, and what's the difference between Layer 4 and Layer 7 load balancing?
A load balancer sits in front of a group of servers and distributes incoming traffic across them, so no single server gets overwhelmed and the system can keep working if one instance goes down. Layer 4 load balancing works at the transport layer, routing based on IP and port without looking at the actual request content, which is fast but less flexible. Layer 7 load balancing works at the application layer, it can inspect the actual HTTP request, headers, URL path, cookies, and route based on that, for example sending /api/video traffic to one set of servers and /api/auth to another.
2. What are common load balancing algorithms, and when would you pick one over another?
Round robin cycles through servers in order, simple but doesn't account for how busy each server actually is. Least connections sends the next request to whichever server currently has the fewest active connections, which handles uneven request durations better. IP hash routes a given client consistently to the same server based on a hash of their IP, useful when you need session affinity ("sticky sessions") without a shared session store. You'd pick least connections for workloads with variable request times, and round robin when requests are roughly uniform in cost.
3. What's a CDN, and why does it help even for dynamic content, not just static files?
A CDN (Content Delivery Network) caches content on servers geographically distributed close to end users, so a user in Mumbai isn't fetching an image from a server in Virginia every time. It's an obvious win for static assets, images, CSS, JS bundles, but modern CDNs also help with dynamic content through edge caching of API responses (for content that doesn't need to be instantly fresh) and by simply terminating the connection closer to the user, which reduces the network round-trip time even for requests that do get forwarded back to your origin server.
4. What's the difference between REST, gRPC, and GraphQL, and when would you pick each?
REST uses standard HTTP verbs and typically JSON payloads, it's simple, widely understood, and easy to debug, but can lead to over-fetching or under-fetching data and often needs multiple round trips for related resources. gRPC uses HTTP/2 and Protocol Buffers for binary serialization, which is much faster and more compact than JSON, and it's commonly used for internal service-to-service communication where performance matters more than human readability. GraphQL lets the client specify exactly which fields it needs in a single request, solving REST's over/under-fetching problem, which makes it a good fit for complex frontends with varied data needs, but it adds complexity on the server side (resolvers, query cost analysis to prevent abuse).
5. What's the difference between a WebSocket and long polling for real-time updates?
Long polling has the client send a request that the server holds open until there's new data (or a timeout), then the client immediately sends another request, it simulates real-time behavior over regular HTTP but still has per-request overhead and some inherent latency. A WebSocket opens a single persistent, full-duplex connection between client and server, either side can push data at any time without the overhead of repeatedly opening new HTTP connections, which makes it a better fit for things like chat apps or live dashboards with frequent updates in both directions.
6. What does DNS resolution actually look like end to end when you type a URL?
Your browser first checks its own cache, then the OS cache, then it queries a DNS resolver (often provided by your ISP). If that resolver doesn't have it cached, it starts a chain: asking a root nameserver, which points to a TLD nameserver (for .com, .in, etc.), which points to the authoritative nameserver for that specific domain, which finally returns the actual IP address. That IP gets cached at multiple levels along the way (browser, OS, resolver) so the full chain usually only happens once per TTL window, not on every single request.
Databases and Storage at Scale
1. SQL vs NoSQL, what's the actual decision framework, not just "NoSQL is for big data"?
SQL databases give you a fixed schema, strong consistency, and powerful joins, which is ideal when your data is naturally relational and you need strict correctness (financial transactions, inventory counts). NoSQL databases trade some of that structure and consistency for flexibility and horizontal scalability, which fits use cases with huge write volume, evolving or unstructured data, or where eventual consistency is an acceptable tradeoff (social media feeds, product catalogs, logging). The real decision isn't "big data means NoSQL," it's whether your data is relational and needs strong consistency, or whether it's flexible and scale matters more than strict correctness.
| Aspect | SQL | NoSQL |
|---|---|---|
| Schema | Fixed, enforced by the database | Flexible, often schema-less |
| Consistency | Strong (ACID transactions) | Often eventual, tunable in some systems |
| Scaling | Mostly vertical, horizontal is harder | Built for horizontal scaling |
| Best for | Relational data, transactions | High write volume, flexible or huge datasets |
2. What is database sharding, and what are common sharding strategies?
Sharding splits a single logical database into multiple smaller physical databases (shards), each holding a subset of the data, so no single machine has to store or serve all of it. Common strategies: range-based sharding (splitting by a value range, like user IDs 1-1M on shard A, 1M-2M on shard B), hash-based sharding (hashing a key to decide which shard it belongs to, which distributes data more evenly but makes range queries harder), and geographic sharding (splitting by region, which also helps with latency for regional users).
3. What's the difference between database replication and sharding, and why do you often need both?
Replication copies the same full dataset onto multiple servers, which helps with read scaling and fault tolerance, if one replica goes down, others still have all the data. Sharding splits the data itself across servers, which helps with write scaling and storage limits, since no single server needs to hold everything. They solve different problems: sharding handles "the dataset is too big for one machine," replication handles "we need redundancy and more read capacity," and large systems typically use both together, sharding to split the data, replication within each shard for redundancy.
4. What is a leader-follower (master-replica) replication setup, and what happens if the leader goes down?
In leader-follower replication, all writes go to a single leader node, which then propagates those changes to one or more follower (replica) nodes, which typically serve read traffic to offload the leader. If the leader goes down, the system needs a failover process, either automatic (a monitoring system promotes a follower to be the new leader) or manual, and there's usually a brief window where writes are unavailable or some very recent writes might be lost if they hadn't fully replicated yet, which is a real tradeoff teams have to plan around.
5. What is an index, and why can't you just index every column to make queries fast?
An index is a separate data structure (commonly a B-tree) that lets the database find rows matching a condition without scanning the entire table, similar to an index at the back of a book. The catch is that every index has to be updated whenever the underlying data changes, so more indexes mean slower writes (inserts, updates, deletes all now have more structures to maintain) and more storage overhead. The real skill is indexing the columns that are actually queried often, especially in WHERE, JOIN, and ORDER BY clauses, not indexing everything defensively.
6. What is eventual consistency, and when is it an acceptable tradeoff?
Eventual consistency means that after a write, different nodes in a distributed system might briefly return different (stale) values, but given enough time with no new writes, all nodes will converge to the same value. It's an acceptable tradeoff when brief staleness doesn't meaningfully hurt the user experience, a "like" count being off by a few for a couple seconds, or a follower count lagging slightly, since it lets you get much better availability and performance in exchange. It's not acceptable for things like account balances or inventory counts where showing stale, incorrect data can cause real problems.
Caching
1. Where would you actually put a cache in a typical web architecture, and why does location matter?
Caches can live at multiple layers: client-side (browser cache), CDN (edge caching close to users), an in-memory application-level cache (like Redis sitting between your app servers and the database), or even inside the database itself (query result caching). Location matters because it changes the tradeoff, a CDN cache reduces load on your entire infrastructure and cuts latency dramatically for static or semi-static content, while an application-level cache mainly protects your database from repeated expensive queries but still requires a network hop from your app server.
2. What are the common cache eviction policies, and how do they differ?
LRU (Least Recently Used) evicts whatever hasn't been accessed in the longest time, which works well when recent access is a good predictor of future access, the common case. LFU (Least Frequently Used) evicts whatever has been accessed the fewest total times, which can be better for workloads with some items that are consistently popular versus a lot of one-off accesses. FIFO just evicts whatever was added first, regardless of how often it's been used, simple but usually the least effective of the three for real-world access patterns.
3. What's the difference between write-through, write-back, and write-around caching?
Write-through writes to the cache and the underlying database at the same time, synchronously, so the cache is always consistent with the database, but writes are slower since you're paying the cost of both. Write-back (write-behind) writes to the cache immediately and asynchronously flushes to the database later, which makes writes fast but risks data loss if the cache fails before the flush happens. Write-around writes go directly to the database, skipping the cache entirely, and the cache only gets populated on a subsequent read, which avoids filling the cache with data that might never be read again, at the cost of a guaranteed cache miss on the first read after a write.
4. What is cache invalidation, and why is it considered one of the genuinely hard problems in computer science?
Cache invalidation is the process of removing or updating cached data once the underlying source data changes, so the cache doesn't keep serving stale results. It's hard because there's no single correct strategy, time-based expiry (TTL) is simple but can serve stale data until it expires, or waste cache hits by expiring too early, event-based invalidation (explicitly clearing a cache entry when the source changes) is more accurate but adds coupling and complexity, especially across distributed caches and services that don't always know about every write that should trigger an invalidation.
5. What is the "thundering herd" problem, and how do you prevent it?
Thundering herd happens when a popular cache entry expires (or the cache goes down entirely), and a large burst of concurrent requests all miss the cache at the same moment and hit the database simultaneously, potentially overwhelming it. Common mitigations: staggering TTLs slightly so not everything expires at the exact same instant, using a "lock" so only one request regenerates the cache entry while others wait briefly for it, and serving slightly stale data while the fresh value is being recomputed in the background (sometimes called stale-while-revalidate).
Scalability and Reliability Patterns
1. What is rate limiting, and what are common algorithms for implementing it?
Rate limiting caps how many requests a client can make in a given time window, protecting your system from abuse, accidental traffic spikes, or a single misbehaving client hogging resources. Token bucket adds tokens to a bucket at a fixed rate, and each request consumes a token, allowing some burstiness up to the bucket's capacity. Leaky bucket processes requests at a fixed, steady rate regardless of how bursty the incoming traffic is, smoothing it out. Sliding window counts requests over a rolling time window rather than fixed, non-overlapping intervals, which avoids the edge case where fixed windows allow two full bursts right at a window boundary.
2. What is the circuit breaker pattern, and what problem does it solve?
A circuit breaker wraps a call to another service and tracks its failure rate, if failures cross a threshold, the circuit "opens" and further calls fail immediately (or fall back to a default) without even attempting the actual request, for a cooldown period. This solves the problem where a struggling downstream service gets hit with repeated retries from callers who keep waiting on timeouts, making the downstream service's overload even worse and potentially cascading the failure across your whole system. After the cooldown, the breaker allows a few test requests through to see if the downstream service has recovered before fully closing again.
3. What is consistent hashing, and why is it better than simple modulo-based hashing for distributing data across servers?
Simple modulo hashing (hash(key) % number_of_servers) breaks badly when you add or remove a server, since the number of servers changes, almost every key now maps to a different server, causing a massive, unnecessary redistribution of data. Consistent hashing maps both servers and keys onto a conceptual ring, and each key belongs to the next server clockwise from it on the ring. Adding or removing a server only affects the keys immediately adjacent to it on the ring, not the entire dataset, which makes scaling in or out far cheaper.
4. What's the difference between a single point of failure and redundancy, and how do you design around SPOFs?
A single point of failure is any component whose failure alone can take down the entire system, a single database with no replica, a single load balancer instance, a single server handling all traffic. Redundancy means having backup components ready to take over, multiple replicas, multiple load balancer instances behind a floating IP or DNS failover, multiple availability zones. You design around SPOFs by identifying every component in your architecture and asking "what happens if this specific piece dies right now," and adding redundancy anywhere the answer is "everything breaks."
5. What is idempotency, and why does it matter for APIs, especially retries?
An idempotent operation produces the same result no matter how many times it's applied, calling it once or ten times leaves the system in the same state. This matters enormously for retries, if a client doesn't get a response (maybe the response was lost on the way back, even though the server actually processed it), it needs to safely retry without accidentally double-charging a payment or creating duplicate records. APIs commonly achieve this with idempotency keys, a unique ID the client generates and sends with the request, so the server can recognize a retry of the same logical operation and just return the original result instead of processing it again.
Messaging and Asynchronous Systems
1. What's the difference between a message queue and a pub/sub system?
A message queue typically delivers each message to exactly one consumer, once a worker picks up a message and processes it, that message is gone from the queue, which is a natural fit for distributing work across a pool of workers. Pub/sub (publish-subscribe) broadcasts each message to every subscriber interested in that topic, multiple independent consumers can each get their own copy of the same event, which fits scenarios where several different services all need to react to the same event independently.
2. Why would you introduce a message queue between two services instead of just calling one directly?
A direct synchronous call couples the two services tightly, if the receiving service is slow or down, the calling service is blocked or fails too. A message queue decouples them: the sender just drops a message and moves on, and the receiver processes it whenever it's ready, which smooths out traffic spikes (the queue absorbs a burst instead of overwhelming the receiver immediately), and lets you scale the number of consumers independently of the number of producers.
3. What's the difference between at-least-once, at-most-once, and exactly-once delivery guarantees?
At-most-once means a message might get lost but will never be delivered twice, simple but risky if losing a message is unacceptable. At-least-once means a message will never be silently lost, but might get delivered more than once (usually due to retries after an ack is lost), which means consumers need to be idempotent to handle duplicates safely. Exactly-once, delivered precisely one time no matter what, is the ideal but genuinely hard to guarantee in a distributed system, most "exactly-once" systems actually implement at-least-once delivery plus deduplication logic on the consumer side to fake the effect of exactly-once.
4. What is a dead-letter queue, and why do production systems need one?
A dead-letter queue is a separate queue where messages get routed after they've failed processing some number of times (rather than being retried forever or silently dropped). It matters because without one, a single malformed or problematic message can get stuck in an endless retry loop, blocking the queue or wasting resources, or it just gets dropped and you lose visibility into the fact that something failed. Routing it to a dead-letter queue instead lets you inspect, alert on, and manually reprocess failed messages without holding up the rest of the pipeline.
5. What's the difference between synchronous and asynchronous communication between microservices, and how do you decide which to use?
Synchronous communication (typically HTTP/REST or gRPC calls) means the caller waits for a response before continuing, simple to reason about but couples the availability and latency of both services together. Asynchronous communication (via a message queue or event stream) means the caller fires off a message and continues immediately, decoupling the two services in time. You'd use synchronous when the caller genuinely needs an immediate response to proceed (checking if a payment succeeded before showing a confirmation page), and asynchronous when the action can happen eventually without blocking the user (sending a confirmation email after an order is placed).
Microservices and API Design
1. What's the actual tradeoff between a monolith and microservices, not just "microservices are better"?
A monolith is simpler to develop, test, deploy, and debug early on, everything is in one codebase and one deployable unit, and there's no network overhead between components since they're just function calls. Microservices let different teams work independently, scale specific components separately, and use different tech stacks per service, but they add real complexity: network calls between services can fail in ways function calls can't, debugging a request across five services is harder, and you need infrastructure for service discovery, distributed tracing, and inter-service communication that a monolith just doesn't need. Microservices genuinely make sense once a monolith's team size or deployment complexity becomes the actual bottleneck, not by default from day one.
2. What is an API gateway, and what does it typically handle that individual services shouldn't have to?
An API gateway sits in front of all your microservices as a single entry point for external clients, routing requests to the appropriate backend service. It commonly handles cross-cutting concerns that would otherwise be duplicated in every single service: authentication, rate limiting, request logging, SSL termination, and sometimes response aggregation from multiple services into a single response for the client. This keeps individual services focused on their actual business logic instead of each reimplementing the same auth and logging code.
3. What is service discovery, and why do you need it in a microservices architecture?
Service discovery is how services find the network location (IP and port) of other services they need to call, which matters because in a dynamic environment, services get scaled up and down, restarted, or moved between hosts constantly, so hardcoding IP addresses just doesn't work. A service registry (like Consul or Eureka, or built into orchestrators like Kubernetes) keeps track of which instances of a service are currently healthy and where they're running, and services query it (or use a sidecar/DNS-based approach) to find each other dynamically instead of relying on static configuration.
4. How do you handle versioning in a public API?
Common approaches: URL versioning (/v1/users, /v2/users), which is explicit and easy for clients to understand but leads to duplicated routes over time; header-based versioning, where the client specifies a version in a request header, keeping URLs clean but less discoverable; and sometimes query parameter versioning. Whichever approach you pick, the more important practice is having a clear deprecation policy, giving clients enough advance notice and a transition window before an old version actually gets shut down, since breaking a public API without warning breaks real integrations.
5. What is the "distributed monolith" anti-pattern, and how does it happen?
A distributed monolith is when a team splits a system into separate services, but those services are still so tightly coupled, sharing a database, requiring synchronized deployments, calling each other in long synchronous chains, that you end up with all the operational complexity of microservices (network calls, more infrastructure to manage) without actually getting the benefits (independent deployability, fault isolation). It usually happens when services are split along technical lines rather than actual business domain boundaries, without really thinking through what data and functionality each service should own independently.
Designing Common Systems
1. How would you approach designing a URL shortener like Bit.ly at a high level?
Start with the core requirement: given a long URL, generate a short, unique code, and redirect users from the short URL back to the original. Key design points: how to generate unique short codes (a counter with base62 encoding is simpler and avoids collisions compared to random generation plus a collision check), a database mapping short codes to original URLs (a key-value store like DynamoDB or Redis fits well here since lookups are simple point reads), and since it's extremely read-heavy (way more redirects than new URLs created), a cache in front of the database and possibly a CDN for the redirect layer makes a big difference. Analytics (click counts) can be handled asynchronously via a message queue so it doesn't slow down the actual redirect.
2. How would you design a rate limiter for an API?
Decide on the granularity first, per user, per IP, per API key, then pick an algorithm (token bucket is a common default for allowing reasonable burstiness). For a single server, an in-memory counter works fine, but for a distributed system with multiple API server instances, you need a shared, fast data store like Redis to track request counts consistently across all instances, since each instance can't just track counts locally without letting a client trivially double their real limit by hitting different servers. You'd also think about what happens when the limit is hit, return a 429 status with a Retry-After header, so well-behaved clients know exactly when to try again.
3. How would you design a notification system that supports email, SMS, and push?
The core idea is decoupling the "something happened, notify the user" event from the actual delivery mechanism. An event triggers a message onto a queue, a notification service consumes it, looks up the user's preferences (which channels they want, do-not-disturb hours), and dispatches to the right channel-specific service, each of which typically wraps a third-party provider (SES/SendGrid for email, Twilio for SMS, FCM/APNs for push). Using a queue here matters because these external providers can be slow or occasionally fail, and you don't want that latency or failure to block whatever triggered the notification in the first place, plus it naturally gives you retry capability if a provider call fails.
4. How would you design a basic chat application, think WhatsApp at a high level?
Real-time delivery between online users typically uses WebSockets, each connected client holds an open connection to a chat server, and messages get routed through that connection. Since a single server can't hold every user's connection, you need a way to know which server a given user is currently connected to (often tracked in a fast lookup like Redis), so a message from user A to user B can be routed to whichever server B is actually connected to. Messages should also be persisted to a database for chat history and for delivering messages to users who are currently offline, delivered once they reconnect, and for group chats, you'd fan out a single message to every online member's respective connection.
5. How would you design a news feed or activity feed system?
Two broad approaches: fan-out on write, where when a user posts, the system immediately pushes that post into the feed storage of all their followers, which makes reading a feed very fast (just read your own pre-built feed) but expensive for users with millions of followers. Fan-out on read builds the feed at request time by pulling recent posts from everyone you follow and merging them, which avoids the "celebrity user" write explosion but makes reads more expensive. Most real systems use a hybrid, fan-out on write for regular users, and fan-out on read (or a special-cased path) for accounts with huge follower counts, to get the best of both.
Low Level Design and OOP Principles
1. What are the SOLID principles, briefly?
Single Responsibility, a class should have exactly one reason to change. Open/Closed, a class should be open for extension but closed for modification, you should be able to add new behavior without editing existing, tested code. Liskov Substitution, a subclass should be usable anywhere its parent class is expected, without breaking correctness. Interface Segregation, don't force a class to implement methods it doesn't actually need, prefer several small, focused interfaces over one large one. Dependency Inversion, high-level modules shouldn't depend directly on low-level modules, both should depend on abstractions.
2. What's the difference between HLD and LLD in a system design interview, and how much of each are you actually expected to cover?
High-Level Design (HLD) is the big picture, the overall architecture, which services exist, how they communicate, how data flows through the system. Low-Level Design (LLD) drills into the actual implementation details of a specific component, class diagrams, method signatures, database schemas, specific algorithms. Most "system design" interviews (especially the classic "design X" format) lean heavily HLD, while LLD-focused rounds (more common at certain companies) ask you to design a specific module in real detail, like an elevator system or a parking lot, using actual classes and their relationships. It's worth knowing which style a given interview expects going in.
3. What's the difference between composition and inheritance, and why do people say "favor composition over inheritance"?
Inheritance models an "is-a" relationship, a subclass inherits the full behavior of its parent, which can get brittle as hierarchies deepen, changes to a base class ripple through everything beneath it, and some languages only allow single inheritance, limiting flexibility. Composition models a "has-a" relationship, a class holds a reference to another object and delegates certain behavior to it, which is more flexible since you can swap out the composed object's behavior at runtime and avoid deep, fragile inheritance chains. It's not that inheritance is always wrong, but composition tends to age better as a codebase grows.
4. What's a design pattern you'd actually use in a real backend service, and why?
The Strategy pattern comes up a lot in real backend code, for example choosing between different payment providers or pricing algorithms at runtime, you define a common interface, implement each variant separately, and the calling code just depends on the interface, not the specific implementation, which makes adding a new provider later a matter of adding a new class instead of editing a big conditional block. The Factory pattern is another common one, centralizing the logic for how to construct a specific type of object so callers don't need to know the construction details.
5. What is the Singleton pattern, and what's a legitimate criticism of overusing it?
A Singleton ensures a class has exactly one instance across the whole application and provides a single global access point to it, commonly used for things like a database connection pool or a configuration manager. The legitimate criticism is that singletons introduce hidden global state, which makes unit testing harder (you can't easily swap in a mock instance since code reaches for the singleton directly instead of receiving it as a dependency), and it can hide the true dependencies a class actually has, since they're not visible in its constructor or function signature the way an injected dependency would be.
Struggling to Find a Job? Get Specific Batch Wise job Updates ✅ Check now