All lessons are available in Azerbaijani. English translations are available for selected lessons. This is not a fully English-language course.
What you will learn
- Turn requirements into measurable technical decisions.
- Choose between caching, sharding, indexes, and consistency tradeoffs.
- Design recovery for repeated requests, contention, and partial failures.
- Complete designs for news feeds, monitoring, and file sharing.
How to approach a system design problem
Start with requirements and a workload estimate. Define the API and data model, trace one request through a simple architecture, then examine failures and bottlenecks. A useful design explains why each component is needed and what happens when it is unavailable.
For backend developers who can already build a small HTTP API. The URL shortener below is an illustrative design exercise, not a description of Bitly's production architecture.
Trace a short-link lookup
Browser requests a code
GET /abc123 identifies the short code. Decide how missing, expired and disabled links behave before discussing cache products or database clusters.
API looks up the mapping
Start with a durable record containing the unique code, destination and optional expiry. A database uniqueness constraint protects the code during concurrent writes; random generation alone does not guarantee uniqueness.
Optional cache serves hot codes
Add a cache when read latency or database load warrants it. On a miss, read the database. Decide how an edited or disabled link invalidates cached data and how to limit database load if the cache fails.
API returns a redirect
Return a redirect with a Location header. A temporary redirect is a useful starting point for editable links. Choose explicit cache behaviour; invalidating your own cache cannot recall a redirect already cached by a client.
| Decision | Simple starting point | Reason to reconsider |
|---|---|---|
| Store code-to-URL mappings | Relational table with a unique code | Measured limits in throughput, size or availability |
| Serve repeated lookups | Read from the database | Hot-code reads create unacceptable latency or load |
| Record click analytics | Define what must be counted and when | Move work off the redirect path if it slows redirects |
| Generate short codes | Generate, insert and handle a collision | Contention, predictability or code-length constraints |
Estimate requests before choosing infrastructure
Run this with Python 3. Assume one million new links and 100 million redirects per day, plus a hypothetical peak five times the daily average. These are exercise inputs, not measured traffic or concurrent-user counts. Real peak load, geography and latency targets need separate evidence.
Run: python3 capacity.py
new_links_per_day = 1_000_000
redirects_per_link = 100
peak_multiplier = 5
seconds_per_day = 24 * 60 * 60
write_rps = new_links_per_day / seconds_per_day
read_rps = write_rps * redirects_per_link
print(f"Average writes/s: {write_rps:.2f}")
print(f"Average reads/s: {read_rps:.2f}")
print(f"Assumed peak reads/s: {read_rps * peak_multiplier:.2f}")Average writes/s: 11.57
Average reads/s: 1157.41
Assumed peak reads/s: 5787.04Try it yourself: Change the peak multiplier to 10. Explain which assumption changed and what did not. This arithmetic does not tell you the number of servers: benchmark request cost, cache misses and failure behaviour before choosing capacity.
Before you start
Should I start with a monolith or microservices?
Begin with the smallest design that meets the requirements. One API and one database make the request path easier to reason about. Separate services when independent ownership, deployment or scaling outweighs network failures and coordination costs.
How do I discuss caching in an interview?
Name the key, cached value, expiry and invalidation rule. Then explain a miss, a stale value and a cache outage. Saying Redis without those behaviours leaves the important design decisions unanswered.
What makes a system design answer convincing?
State assumptions, compare alternatives and follow a failure through the system. For example, explain how two requests competing for the same short code are handled. A smaller design with clear behaviour is easier to evaluate than a diagram full of unexplained services.