Fanpilot

System design

System design interview questions

27 min read

These are the questions that come up in high-level design (HLD) interviews: how services, databases, caches, and networks fit together at scale. Each answer gives the standard version first, the one interviewers expect. Then, where it matters, where it breaks down: the limits of the textbook answer, the tradeoffs it skips, and a few common answers that are simply wrong.

For classes, interfaces, and patterns, see the object design questions. For a step-by-step method for design interviews, see the system design guide.

The basics

What goes into a high-level design?

A high-level design names the major parts and how requests flow between them: clients, load balancers, application services, databases, caches, queues, and outside services. For an online store, that might be a user service, a product service, a payment service, a database for each, a cache for popular products, and a load balancer in front. It also covers how the system scales, stays up, and stays secure.

Where it breaks down: a diagram of boxes isn't a design. The design is the reasons: why this database, what happens when that service is slow, how much traffic each part handles. Interviewers care more about your explanations of two or three key decisions than about how many boxes you draw.

What are latency, throughput, and availability?

  • Latency: how long one request takes, such as 200 milliseconds to load a page.
  • Throughput: how many requests the system handles per unit of time, such as 10,000 per second.
  • Availability: the fraction of time the system works. "Three nines", 99.9%, allows about 8.8 hours of downtime a year; 99.99% allows about 53 minutes.

A video site needs low latency so playback starts fast, high throughput for millions of viewers, and high availability so it's always up.

Where it breaks down: averages hide the pain. If the average latency is 100 ms but 1 in 100 requests takes 3 seconds, those users have a bad time, and a page that makes 100 backend calls hits at least one slow call about 63% of the time. Measure percentiles, like p99 (the slowest 1%). Availability also multiplies: a request that needs five services, each 99.9% available, works only about 99.5% of the time.

Architecture

Monolith or microservices?

A monolith is one program, deployed as one unit. It's simpler to build, test, and deploy, and calls between parts are plain function calls. Microservices split the system into separately deployed services that talk over the network. Each can scale and deploy on its own, and different teams can own different services. The common advice: start with a monolith, and split when the system and the team grow.

Where it breaks down: microservices trade code complexity for operational complexity: network failures, retries, versioned APIs, distributed tracing, and data spread across databases. The worst outcome is a "distributed monolith": services that must all deploy together because they share a database or call each other in long chains. You pay every cost of microservices and get none of the benefits. A modular monolith, with strong module boundaries inside one program, gets you most of the organization without the network. Split out a service when one part truly needs to scale or deploy independently.

What's the difference between stateful and stateless services?

A stateful server remembers something about each client between requests, like a login session in its memory, so later requests must reach the same server. A stateless server keeps nothing between requests: every request carries what's needed, such as a token, or the server looks it up in a shared database or cache. Any server can handle any request, so scaling is just adding servers.

Where it breaks down: "stateless" doesn't mean there's no state. It means the state moved somewhere shared, like a database or Redis, and that place now has to scale and stay available. Some things are stateful by nature: databases, WebSocket connections for chat, and multiplayer game servers. Stateless signed tokens (JWTs) have their own catch: you can't easily revoke one before it expires.

Synchronous or asynchronous communication?

With synchronous calls, the caller waits for the answer, as with a normal HTTP request. With asynchronous communication, the caller hands off a message, often to a queue, and moves on; someone else handles it later. Payment checks are usually synchronous, because the user is waiting for the answer. Sending a confirmation email is usually asynchronous.

Where it breaks down: async isn't free speed. Work still has to happen; you've just moved it out of the request. Now you need to handle messages that are delayed, delivered twice, or fail after the user was told "done". Use async for work the user doesn't need to wait for, and keep it sync when they need the result to continue.

What is event-driven architecture?

Instead of calling each other directly, services publish events, like "order placed", to a broker such as Kafka. Any service that cares subscribes: payments, inventory, and notifications each react on their own. The order service doesn't need to know who's listening, so adding a new consumer requires no change to it.

Where it breaks down: the flow of the system becomes invisible in the code. To understand what happens after an order, you have to find every subscriber. Events arrive late, out of order, or twice, so every consumer must handle that. A classic bug is the "dual write": the service saves the order to its database and then publishes the event, and crashes in between, so one happens without the other. The usual fix is the outbox pattern: write the event to a table in the same database transaction as the order, and publish from that table separately.

What does a message broker or message queue do?

A broker, like RabbitMQ, Kafka, or Amazon SQS, sits between services. Producers send messages; the broker stores them; consumers process them at their own pace. That absorbs traffic spikes (the queue grows, and consumers catch up), lets services fail independently, and decouples who sends from who handles.

Where it breaks down: three things the textbook skips.

  • Delivery is usually "at least once". A consumer can crash after doing the work but before acknowledging it, so the message comes again. Make handlers idempotent: processing a message twice must have the same effect as once.
  • Kafka isn't a queue. It's a log: messages stay for a set time, and each consumer group tracks its own position. Many groups can read the same messages, and you can replay old ones. RabbitMQ and SQS are queues: a message is gone once it's handled.
  • Poison messages. A message that always fails will be retried forever unless you send it to a dead-letter queue after a few attempts.

What does an API gateway do?

An API gateway is the single front door for clients in a microservices system. It routes each request to the right service and handles shared concerns in one place: authentication, rate limiting, logging, and sometimes combining several service calls into one response.

Where it breaks down: every request now passes through it, so it must be highly available and fast. And it attracts business logic it shouldn't have, until it's a monolith in disguise. Keep it to routing and cross-cutting concerns.

What's a reverse proxy, and how is it different from a load balancer or API gateway?

A reverse proxy, like Nginx, sits in front of your servers and forwards client requests to them. Clients never talk to your servers directly. It can terminate HTTPS, cache responses, compress data, and hide your internal layout.

Where it breaks down: the three overlap heavily in practice. A load balancer is a reverse proxy that spreads traffic across servers; an API gateway is a reverse proxy with routing and policies for APIs. Nginx or Envoy can play all three roles. In an interview, describe what the component does rather than arguing about its name.

What is service discovery?

In a system where servers come and go, services can't hard-code each other's addresses. Service discovery keeps a live registry of where each service is running. Kubernetes does it with internal DNS: a service called payments is reachable at that name, wherever its servers currently are.

Where it breaks down: stale entries. A crashed server can stay in the registry until a health check notices, and DNS answers are cached by clients. Callers need timeouts and retries for the window when the registry is wrong.

What are the benefits of containers?

A container packages an app with everything it needs (libraries, runtime, configuration) so it runs the same on a laptop and in production. Containers start fast and pack densely onto machines. An orchestrator such as Kubernetes restarts failed containers, scales them up and down, and rolls out new versions.

Where it breaks down: containers share the host's operating system kernel, so they isolate less than virtual machines do. Running untrusted code needs more isolation. And Kubernetes is a large system to operate; small teams often do better with a simpler managed platform.

What are the steps to design an API?

Identify the resources (users, products, orders), the operations on them, and the request and response formats. Then decide on authentication, error format, pagination, rate limits, and versioning, and document it. For an online store: GET /products, POST /orders, JSON bodies, and a token in the header.

What are the principles of RESTful API design?

REST treats things as resources with URLs, and uses HTTP methods as the verbs: GET /users/1 reads, POST /users creates, PUT replaces, PATCH updates part, DELETE removes. Responses use standard status codes, like 201 for created, 404 for not found, and 429 for too many requests. Each request carries everything needed, with no server-side session.

Where it breaks down: two things matter more than URL style. Retries: GET, PUT, and DELETE are meant to be idempotent, but POST isn't. If a client retries "create order" after a timeout, it may create two orders. Accept an idempotency key with the request and ignore repeats. Fit: REST isn't the only choice. GraphQL suits clients that need flexible queries, and gRPC suits fast calls between internal services.

Scaling

Horizontal or vertical scaling?

Vertical scaling means a bigger machine: more CPU, memory, or disk. Horizontal scaling means more machines behind a load balancer. Vertical is simpler but has a ceiling and a single point of failure. Horizontal has no hard ceiling and survives a machine dying, but the app must be able to run as many copies.

Where it breaks down: people reach for horizontal too early. A single large modern server, with dozens of cores and hundreds of gigabytes of memory, handles far more than most products ever need, and one big database server is much simpler than a sharded one. Scale the stateless parts horizontally, which is easy. Scale the database vertically as long as you can, because splitting data is hard.

How do you design a system to scale?

Find what will run out first, then fix that. The usual tools: run many copies of stateless services behind a load balancer; cache hot data; move slow work to queues; serve static files from a CDN; add read replicas for read-heavy data; and shard the data when one database can't keep up. A video platform might use a CDN for video, Redis for metadata, and many app servers.

Where it breaks down: scaling is driven by numbers, not by a list of techniques. Estimate requests per second, data size, and read/write mix first. A system with 50 requests per second doesn't need sharding, and adding it anyway costs you complexity with nothing in return.

What does a load balancer do?

It spreads incoming requests across a pool of servers, so no single one is overwhelmed, and it stops sending traffic to servers that fail. Common ways to choose a server: round robin, fewest active connections, or a hash of the client. Examples: Nginx, HAProxy, AWS Elastic Load Balancing.

Where it breaks down: a load balancer is itself a single point of failure unless it's redundant, so it's usually a pair or a managed service. There are two kinds. Layer 4 balancers route by IP and port and are very fast. Layer 7 balancers read the HTTP request, so they can route by URL or header. And spreading requests evenly doesn't mean spreading load evenly: one expensive request can cost as much as a thousand cheap ones.

How do load balancer health checks work?

The load balancer regularly sends each server a small test request, like GET /health. If a server fails several checks in a row, it's taken out of rotation until it passes again. In a food delivery app with four servers, if one crashes, users are sent to the other three within seconds.

Where it breaks down: two traps. First, a health check that also checks the database can take every server out at once when the database hiccups, turning a small problem into a full outage. Kubernetes separates "is this process alive?" (liveness) from "can it take traffic right now?" (readiness) for this reason. Second, a server can pass health checks and still return errors on real requests, so also watch actual error rates.

What are sticky sessions?

The load balancer sends all requests from one user to the same server, usually by cookie, so session data kept in that server's memory, like a shopping cart, stays available.

Where it breaks down: if that server dies, its users lose their sessions. Load gets uneven, since some servers collect heavy users. And you can't freely add or remove servers. The usual better answer: keep session data in a shared store like Redis, so servers stay stateless and any of them can handle any request.

How does auto-scaling work?

The platform watches a metric, such as CPU use or requests per second, and adds servers when it's high and removes them when it's low. An online store adds servers during a holiday sale and drops them afterward, so you pay only for what you use.

Where it breaks down: new servers take time to start, often minutes. A sudden spike hits before they're ready, so keep some headroom or scale on a schedule for known events. CPU is often the wrong signal: for a worker pool, queue length tells you more. And auto-scaling app servers just moves the bottleneck to the database, which can't add capacity in minutes.

What is rate limiting?

Rate limiting caps how many requests a client can make in a time window, such as 100 per minute per user. Extra requests get rejected with HTTP 429. It protects the system from overload and abuse, and keeps one heavy user from crowding out everyone else.

Where it breaks down: the algorithm matters. A fixed window ("100 per calendar minute") allows a burst of 200 around the minute boundary. A token bucket (tokens refill at a steady rate; each request spends one) allows short bursts while capping the average, which is why it's the most common choice. With many servers, the counts must live somewhere shared, like Redis, or each server enforces its own separate limit.

What is a CDN?

A content delivery network is a set of servers around the world that cache your content close to users. A viewer in Tokyo gets an image or a video segment from a nearby server instead of your data center in Virginia, which is faster for them and less load for you.

Where it breaks down: CDNs work best for content that's the same for everyone, like images, scripts, and video. A personalized page can't be cached as a whole. Updating cached content needs a plan: either purge it, or put a version in the file name (app.3f9a.js) so new content gets a new URL. Most sites use the second.

Caching

What is caching, and what are the update strategies?

A cache keeps a copy of frequently read data in fast memory, often Redis or Memcached, so most reads skip the slower database. The main strategies:

Strategy How it works Watch out for
Cache-aside The app reads the cache; on a miss, reads the database and fills the cache. The first read of anything is slow, and data can go stale.
Write-through Every write goes to the cache and the database together. Slower writes, and the cache fills with data nobody reads.
Write-back Writes go to the cache; it saves to the database later. Data is lost if the cache dies before saving.
Write-around Writes go only to the database; the cache fills on reads. A read right after a write misses the cache.

Cache-aside is the most common default.

Where it breaks down: a cache is a second copy, and two copies can disagree. Decide up front how stale each kind of data may be. A product description can be an hour old; a bank balance can't be cached carelessly at all.

What happens on a cache miss?

The data isn't in the cache, so the app reads it from the database, which is slower, then usually stores it in the cache for next time.

Where it breaks down: the dangerous case is a cache stampede. A popular key expires, and thousands of requests miss at the same moment and all hit the database together. Fixes: let only one request rebuild the value while others wait or get the old value; refresh popular keys before they expire; and add a little randomness to expiry times so keys don't all expire at once.

How do you invalidate a cache?

Remove or update cached data when the source changes, so users don't see stale values. Options: expire entries after a set time (TTL), update the cache on every write, or delete the cache entry when the database changes. When a price changes, delete that product's cache entry.

Where it breaks down: "There are only two hard things in computer science: cache invalidation and naming things." The hard part is races. If one request reads an old value from the database while another updates it, the old value can be written into the cache after the delete, and stay there. A TTL on every entry is the safety net: even when invalidation fails, stale data eventually expires.

What happens when a cache is full?

The cache tracks how much memory it uses. When adding an entry would go over its limit, it evicts entries according to a policy: least recently used (LRU), least frequently used (LFU), or soonest to expire. The LRU cache lab builds one from scratch.

Where it breaks down: Redis, the most common cache, doesn't evict by default. Its default policy is noeviction: once it reaches its memory limit, writes fail with an error. You have to set a policy such as allkeys-lru. Redis's LRU is also approximate: it samples a few keys and evicts the oldest of those, trading exactness for speed.

What is a distributed cache?

A cache spread across several servers, like a Redis Cluster, so it holds more data and serves more traffic than one machine could. Each key lives on one server, chosen by hashing the key. An online store can keep product details for millions of products in one.

Where it breaks down: a few very popular keys, say a celebrity's profile, all land on one server and overload it, no matter how many servers you add. Fixes include keeping a small local cache in each app server for the hottest keys, or copying hot keys to several servers. And if the cache goes down, every request falls through to the database at once, which often takes the database down too. Plan for the cache being empty.

Data

SQL or NoSQL?

Relational (SQL) databases, like PostgreSQL and MySQL, store structured data in tables, support joins and complex queries, and offer transactions that keep data consistent. NoSQL databases, like MongoDB, Cassandra, and DynamoDB, offer flexible schemas and are built to spread across many machines. The usual answer: SQL for structured data that must be consistent, such as banking; NoSQL for huge scale or loosely structured data.

Where it breaks down: the line is much blurrier than this. PostgreSQL stores and queries JSON documents well. MongoDB has supported multi-document transactions since version 4.0. Distributed SQL databases like Google Spanner and CockroachDB scale across machines with full transactions. A better way to choose is by access pattern: if you know your queries in advance and need massive write throughput, a key-value or wide-column store like DynamoDB or Cassandra fits. If you'll need ad hoc queries and joins, start with PostgreSQL. Most products should start with PostgreSQL.

What's the difference between ACID and BASE?

ACID describes transactions in relational databases: atomic (all or nothing), consistent (rules always hold), isolated (concurrent transactions don't see each other's half-done work), and durable (once saved, it stays saved). BASE describes many distributed NoSQL systems: basically available, soft state, and eventually consistent. They prefer staying up over always agreeing right away.

Where it breaks down: it's not a two-way choice. Cassandra lets you pick the consistency level per query. Many relational databases default to a weaker isolation level than people assume, such as "read committed", which still allows some anomalies. Know which guarantees your actual database gives at its actual settings.

What is database replication?

Keeping copies of the data on several servers. Usually one primary takes writes and copies them to replicas, which serve reads. That spreads read traffic and gives you a ready copy if the primary dies. An online store sends writes to the primary and product searches to replicas.

Where it breaks down: replicas lag behind the primary, from milliseconds to minutes under load. A user who updates their profile and immediately reloads may read from a replica that hasn't caught up and see the old value. Fixes: read a user's own data from the primary for a short while after they write, or track which version they've seen. And when the primary fails, any writes not yet copied can be lost unless replication is synchronous, which is slower.

What's the difference between partitioning and sharding?

Both split a large dataset into smaller pieces. Partitioning usually means splitting a table within one database server, such as orders by month. Sharding means spreading the pieces across separate servers, such as users A–M on one server and N–Z on another, so the data and load exceed one machine.

Where it breaks down: the shard key is the decision that matters, and it's hard to change later. Shard users by ID, and a query for "all users in Berlin" must ask every shard. A key that's too popular, like one celebrity's ID, creates a hot shard. Joins and transactions across shards become hard or impossible. And moving data when you add shards (resharding) is a project. Shard as late as you can.

What is consistent hashing?

A way to assign keys to servers so that adding or removing a server moves only a small fraction of keys. With plain hash(key) % N, changing N from 4 to 5 moves about 80% of keys. Consistent hashing places servers and keys on a ring, and each key belongs to the next server clockwise. Adding a server only takes keys from its neighbor. Real systems give each server many points on the ring ("virtual nodes") to balance the load.

Where it breaks down: a common claim is that Redis Cluster uses consistent hashing. It doesn't. Redis Cluster splits keys into 16,384 fixed hash slots and assigns slots to servers. Moving data means moving slots. Consistent hashing is used by systems like Amazon's Dynamo and Cassandra, and by many client-side caching libraries. Both approaches solve the same problem: limiting data movement when the cluster changes.

How do you keep data consistent in a distributed system?

Decide, per kind of data, how much disagreement is acceptable. Strong consistency means every read sees the latest write. It's what a bank balance needs, and it costs coordination between servers. Eventual consistency means copies may briefly disagree but converge. A like count can tolerate that. Tools include transactions, idempotent operations (safe to repeat), and rules for resolving conflicts.

Where it breaks down: distributed transactions, like two-phase commit, are slow and fragile: if the coordinator fails at the wrong moment, everyone waits. Most real systems avoid them. Instead they use sagas: a series of local steps, each with an undo ("compensating") step if a later one fails. Book the flight, then the hotel. If the hotel fails, cancel the flight.

What is the CAP theorem?

The CAP theorem says a distributed system can't guarantee all three of consistency (every read sees the latest write), availability (every request gets a response), and partition tolerance (it keeps working when the network splits). It's often stated as "pick two": banks pick consistency, social media picks availability.

Where it breaks down: "pick two" is misleading. Network splits happen whether you like it or not, so partition tolerance isn't optional. The real choice is narrower: during a network split, either refuse some requests to stay consistent, or answer them and risk stale data. When the network is fine, you can have both. The more useful question is the one CAP leaves out: how much latency will you pay for consistency in normal operation? The PACELC model adds that tradeoff. And most systems make different choices for different data, not one choice for the whole system.

How do you ensure data integrity?

Make the database reject bad data and keep related changes together. Use constraints (foreign keys, unique, not null), validate input, and use transactions so related changes succeed or fail together: in a transfer, the debit and credit both happen or neither does. Checksums catch corrupted data, and backups let you recover from mistakes.

Where it breaks down: integrity rules in application code alone get bypassed: by a second service, a script, or a bug. Put the critical rules in the database itself. And backups you've never restored from aren't backups; test restoring them.

How do you handle concurrent writes to shared data?

Several users changing the same data at once can overwrite each other's changes. Two ways to prevent it:

  • Pessimistic locking: lock the row while you work on it (SELECT ... FOR UPDATE), so others wait.
  • Optimistic concurrency: read a version number, and when saving, only update if the version hasn't changed. If it has, retry.

Databases also offer isolation levels, and many use multi-version concurrency control (MVCC), so readers see a consistent snapshot without blocking writers.

Where it breaks down: pessimistic locks reduce throughput and can deadlock. Optimistic concurrency wastes work when conflicts are common. Often the simplest fix is a single atomic statement: UPDATE accounts SET balance = balance - 80 WHERE id = 7 AND balance >= 80. The check and the change can't interleave, so no lock is needed.

Reliability

How do you ensure high availability?

Remove single points of failure: run several copies of each component, replicate data, spread across availability zones (separate data centers in one region), and put load balancers in front that route around failures. Monitor everything, and fail over automatically.

Where it breaks down: redundancy only helps if failures are independent. Two copies in the same rack, or a bad deployment pushed to every server at once, fail together. Most outages come from changes, like deployments and configuration updates, not from hardware. So roll out gradually, and make rolling back fast.

What is fault tolerance?

The ability to keep working when parts fail. If the recommendation service on a shopping site goes down, product pages should still load, just without recommendations. Tools: redundancy, timeouts, retries, circuit breakers, and graceful degradation: deciding in advance which features can switch off.

Where it breaks down: retries can make things worse. When a service struggles, every client retrying at once multiplies its load, a retry storm. Retry only a few times, with exponential backoff (wait longer after each failure) and random jitter, and only for operations that are safe to repeat. Always set timeouts: a call with no timeout can hang forever and tie up your threads.

What is the circuit breaker pattern?

A circuit breaker sits around calls to another service. While calls succeed, it's closed and passes them through. After too many failures, it opens: calls fail immediately, or return a fallback, without waiting on the struggling service. After a pause it goes half-open and lets a few test calls through; if they succeed, it closes again. This stops one failing service from dragging down everything that calls it.

Where it breaks down: the hard part is the settings. Trip too easily, and a brief blip blocks healthy traffic. Trip too slowly, and threads pile up anyway. And a fallback must be truly safe: "payment service down, so assume payment succeeded" is a disaster.

What is leader election?

In some clusters, one node must coordinate, such as deciding the order of writes. Leader election picks that node, and picks a new one if it fails. Nodes send each other heartbeats; if the leader goes quiet for long enough, the others hold an election using an algorithm like Raft or Paxos, or use a coordination service such as ZooKeeper or etcd.

Where it breaks down: the dangerous case is split brain: the old leader isn't dead, just slow or cut off, and keeps acting as leader while a new one is elected. Two leaders write conflicting data. Fixes: a leader must hold a lease that expires, and every write carries a fencing token, an increasing number, so storage rejects writes from an outdated leader. Timeouts are a tradeoff too: short ones cause needless elections, long ones mean longer outages.

What happens when a leader node fails?

The other nodes notice missing heartbeats, wait out a timeout, and elect a new leader, often a replica that's fully up to date. Clients reconnect to the new leader. In a database cluster, a replica is promoted to primary.

Where it breaks down: writes the old leader accepted but hadn't copied yet can be lost. If replication was asynchronous, a few seconds of data can vanish. Systems that can't lose writes use synchronous replication or consensus, where a write isn't confirmed until a majority has it. That costs latency on every write.

How do you design for disaster recovery?

Plan for losing a whole data center or region. Take backups, replicate data to another region, and be able to switch over. Two numbers define the plan: RPO (recovery point objective), how much recent data you can afford to lose, and RTO (recovery time objective), how long you can afford to be down.

Where it breaks down: a plan you haven't practiced doesn't work. Teams discover during a real disaster that backups are incomplete or that failover takes hours of manual steps. Run failover drills regularly. And tighter RPO and RTO cost a lot more: near-zero data loss across regions means waiting for the other region to confirm every write.

How do you make network infrastructure fault-tolerant?

Avoid single points of failure in the network too: redundant links and switches, multiple availability zones, load balancers that route around failed servers, and DNS or routing that can send traffic to a healthy region.

Where it breaks down: DNS failover is slow, because clients and resolvers cache answers for the record's time to live (TTL), sometimes longer. Shorten TTLs ahead of time if you plan to rely on it. Shared dependencies also defeat redundancy: two "independent" links that run through the same conduit get cut by the same backhoe.

Security

How do you handle security in a high-level design?

Build it into every layer from the start: encrypt traffic with TLS (HTTPS), authenticate users (OAuth 2.0 or OpenID Connect, with multi-factor login), authorize every request on the server, validate input, store secrets in a secrets manager rather than in code, and log access. Zero trust means not trusting a request just because it comes from inside your network; services authenticate each other too.

Where it breaks down: the biggest risks are usually ordinary: broken access checks (one user can read another's data by changing an ID in the URL), leaked credentials, and outdated dependencies with known holes. Check permissions on every request, give each service only the access it needs, and keep dependencies updated.

How do you design for data privacy?

Collect only what you need, encrypt sensitive data in transit and at rest, limit who can access it by role, mask it in logs and non-production copies, and record every access. A health app encrypts patient records, restricts them to the patient's care team, and logs each view, as regulations like HIPAA require.

Where it breaks down: deletion is the hard part. Laws like GDPR give people the right to have their data erased, but copies live in backups, logs, caches, analytics systems, and third-party tools. One technique is crypto-shredding: encrypt each user's data with its own key, and delete the key to make every copy unreadable.

Networking

What is the OSI model?

A reference model that splits networking into seven layers: physical, data link, network, transport, session, presentation, and application. Each layer relies on the one below. Loading a website touches all of them, from the electrical signal to the HTTP request.

Where it breaks down: the internet doesn't actually follow OSI; it runs on TCP/IP, which has four layers. OSI survives as vocabulary: "a layer 4 load balancer" routes by IP address and port, and "layer 7" means it reads HTTP. Know the layer numbers that people use (3 for IP, 4 for TCP and UDP, 7 for HTTP), not a memorized list of all seven.

What is the TCP/IP model?

The model the internet actually runs on, with four layers: application (HTTP, DNS, SMTP), transport (TCP, UDP), internet (IP, which routes packets between networks), and link (Ethernet, Wi-Fi). Sending an email uses SMTP at the application layer, over TCP, over IP.

HTTP or HTTPS?

HTTP sends data as plain text, which anyone on the network path can read or change. HTTPS is HTTP over TLS: the connection is encrypted, and the server proves its identity with a certificate. Banking and payments obviously need HTTPS.

Where it breaks down: the old advice that HTTP is "fine for non-sensitive sites" is outdated. Browsers mark HTTP pages as not secure, newer web features require HTTPS, and an attacker can inject content into any unencrypted page. Free certificates from Let's Encrypt removed the cost. Use HTTPS everywhere. (TLS replaced SSL years ago, though people still say "SSL".)

TCP or UDP?

TCP sets up a connection and guarantees that data arrives complete and in order, resending anything lost. It's used for web pages, APIs, and file transfers. UDP just sends packets, with no guarantee they arrive or arrive in order. It's lighter and has no delays from waiting on lost packets, so it suits real-time uses like games, voice calls, and live video chat.

Where it breaks down: "video streaming uses UDP" is a common wrong answer. Netflix and YouTube stream over HTTP, which means over TCP, because buffering a few seconds hides any delay and you want every frame intact. UDP fits live, interactive media, where a late packet is useless. And the line is moving: HTTP/3 runs over QUIC, which is built on UDP and adds its own reliability, so much web traffic now travels over UDP.

Why does DNS matter?

DNS translates names like google.com into IP addresses, like a phone book for the internet. Your browser asks a DNS resolver, which looks up the name and caches the answer for a while.

Where it breaks down: DNS is a common cause of outages. A bad DNS change spreads everywhere and can take hours to undo, because of caching. And DNS is also a load balancing and failover tool, where that same caching makes changes slow to take effect. Plan TTLs before you need to change a record, not during an emergency.