AlgoDaily

System Design Primer for Google Interviews

Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.

Why System Design

From coding patterns to systems

Now that you've finished Intermediate Python for Google Interviews and Advanced Algorithms and Data Structures, you can solve many algorithmic problems locally: one process, one input, one answer.

System design asks a different question:

How would this work for millions of users, many machines, failures, delays, and changing requirements?

For Google-style interviews, you are not expected to magically know every production detail. You are expected to communicate clearly, make reasonable assumptions, identify bottlenecks, and explain tradeoffs.

In this lesson, we'll build a practical primer you can use even if you code part-time: a repeatable structure for discussing large systems.

Why System Design

Interview Roadmap

The 6-step system design loop

Use this loop to stay calm and structured:

  1. Clarify requirements — What are we building? For whom?
  2. Estimate scale — Users, requests per second, storage, bandwidth.
  3. Define APIs — What operations does the system expose?
  4. Sketch data model — What needs to be stored?
  5. Design architecture — Clients, services, databases, caches, queues.
  6. Discuss tradeoffs — Consistency, latency, availability, cost, failure handling.

A useful interview phrase:

"I'll start with requirements and scale, then propose a simple design, find bottlenecks, and improve it."

Interview Roadmap

First Move

In a Google-style system design interview, what is usually the best first move after hearing the prompt?

Estimate Scale

Back-of-the-envelope math

System design interviews often reward reasonable estimates more than exact numbers.

You might estimate:

  • Daily active users
  • Requests per second, also called QPS
  • Read/write ratio
  • Storage growth per day
  • Hot paths that need low latency

This is where your algorithmic thinking still helps. In Advanced Algorithms and Data Structures, you practiced reasoning about complexity. Here, we reason about system load.

Example: if a service receives 10 million requests per day, what is the average QPS?

```python
# Back-of-the-envelope QPS estimation
requests_per_day = 10_000_000
seconds_per_day = 24 * 60 * 60
avg_qps = requests_per_day / seconds_per_day

# Interviews often assume peak traffic is higher than average.
peak_multiplier = 5
peak_qps = avg_qps * peak_multiplier

print(f'Average QPS: {avg_qps:.2f}')
print(f'Estimated peak QPS: {peak_qps:.2f}')
```

Core Architecture

A basic web system shape

Most interview systems start with this mental model:

Users
  |
Load Balancer
  |
Application Servers
  |
Database

Then you add components only when the requirements justify them:

  • Cache for fast repeated reads
  • Queue for background or bursty work
  • Search index for text lookup
  • Object storage for large files like images/videos
  • CDN for static content near users

A strong answer does not add complexity early. It starts simple, then evolves when scale or reliability demands it.

Core Architecture

Find Bottlenecks

Fill in the blank:

If many users repeatedly request the same data and the database is becoming overloaded, a common component to add is a ____.

Reads And Writes

Scale depends on access pattern

A system with mostly reads is different from a system with heavy writes.

Read-heavy systems

Examples: news feeds, product pages, profile views.

Common tools:

  • Cache popular data
  • Read replicas
  • CDN for static assets
  • Precomputed views
Write-heavy systems

Examples: messaging, analytics events, logging.

Common tools:

  • Queues for buffering
  • Partitioning or sharding
  • Batch processing
  • Idempotent writes

Interview tip: always ask for the read/write ratio. It tells you where the pressure will be.

Reads And Writes

Cache Claim

True or false:

Adding a cache always makes a system simpler and more correct.

Mini Design

Example: URL shortener

Prompt: design a service like bit.ly.

Start with requirements:

  • Create a short URL for a long URL
  • Redirect from short URL to long URL
  • Track basic metadata, maybe creation time and owner
  • High read volume: redirects are much more frequent than creation

Simple API:

POST /shorten { long_url }
GET /{short_code} -> redirect

Simple data model:

short_code -> long_url, created_at, user_id

The core problem is generating a compact code and looking it up quickly. In production you would discuss collisions, abuse prevention, expiration, and analytics, but keep the first design focused.

```python
# Tiny educational short-code generator using hashing.
# This is not a full production URL shortener; it demonstrates the mapping idea.
import hashlib

alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

def base62(num):
    if num == 0:
        return alphabet[0]
    chars = []
    while num > 0:
        num, rem = divmod(num, 62)
        chars.append(alphabet[rem])
    return ''.join(reversed(chars))

def short_code(long_url, length=7):
    digest = hashlib.sha256(long_url.encode()).hexdigest()
    num = int(digest[:12], 16)
    return base62(num)[:length]

urls = [
    'https://example.com/python-interview-prep',
    'https://example.com/system-design-primer'
]

for url in urls:
    print(url, '->', short_code(url))
```

Partitioning Data

When one database is not enough

If one database cannot handle the traffic or storage, you may split data across multiple machines. This is called partitioning or sharding.

Common shard keys:

  • user_id
  • tenant_id
  • region
  • short_code

Good shard keys distribute load evenly. Bad shard keys create hot shards, where one machine gets too much traffic.

This connects to the hashing patterns you saw in Intermediate Python for Google Interviews: hashing is often used to map an item to a bucket.

```python
# Simple hash-based sharding demo
users = ['alice', 'bob', 'charlie', 'diana', 'eve', 'frank']
shard_count = 3

for user in users:
    shard = hash(user) % shard_count
    print(f'user={user:7} -> shard {shard}')

print('Note: Python hash randomization may vary between runs.')
```

Tradeoff Language

You are designing a global service. Users should still be able to read data during a regional outage, but some data may be briefly stale. Which tradeoff are you most likely making?

Google Interview Lens

What interviewers listen for

A strong system design answer sounds like an engineer thinking out loud:

  • "Let me clarify the goal and constraints."
  • "Given this traffic estimate, the first bottleneck is likely reads."
  • "I'll start with a simple design and add cache/read replicas only when needed."
  • "This improves latency, but introduces stale data risk."
  • "If writes become hot, I would consider sharding by user or entity ID."

You do not need to memorize every product architecture. You need a reliable conversation structure.

Next, Python Best Practices and Optimization Techniques will zoom back into writing cleaner and faster Python. For now, your goal is to explain systems clearly before optimizing code.

Google Interview Lens

Open interactive view →