Hello! Welcome to the first lesson in our module on Foundational Design Problems.
In the previous module, we explored core infrastructure components like blob storage and CDNs. You learned how a CDN, through its global network of edge servers, dramatically reduces latency for users accessing static content. These components are the building blocks for the large-scale systems you'll be asked to design in interviews.
Now, we'll start putting these blocks together to solve a classic end-to-end system design problem. Your learning outcome for this lesson is to design a URL shortening service (TinyURL). This question is a favorite in interviews because it seems simple on the surface but contains deep challenges related to scalability, data modeling, and distributed systems—all areas where a senior engineer like you is expected to shine.
We will approach this problem using the systematic framework we established in Module 1, covering:
- Clarifying Requirements
- Back-of-the-Envelope Estimation
- API Design
- High-Level Architecture
- Deep Dives into critical components like unique ID generation, database design, and scaling strategies.
1. The Framework: A Systematic Approach
Before diving in, let's quickly watch a clip that recaps the structured approach we'll be following. This is the exact methodology you should use to guide the conversation in a real interview.
Beginner System Design Interview: Design Bitly w/ a Ex-Meta Staff Engineer
This video from 'Hello Interview' outlines a clear, step-by-step framework for tackling any system design problem. We will use this structure for our TinyURL design.
Watch from 01:46 to 03:24. Pay attention to the sequence: Requirements -> Entities -> API -> High-Level Design -> Deep Dives. This structure ensures you cover all bases before getting lost in implementation details.
2. Step 1: Clarifying Requirements
The first and most critical step is to scope the problem. Don't make assumptions. A senior candidate is expected to lead this conversation.
Let's watch how an experienced engineer clarifies the requirements for a URL shortener.
Beginner System Design Interview: Design Bitly w/ a Ex-Meta Staff Engineer
Continuing with the 'Hello Interview' video, let's observe the process of defining both functional and non-functional requirements.
Watch from 03:24 to 12:31. As you watch, take note of: Functional Requirements (03:24): Core features like creating a short URL and redirection, plus optional ones like custom aliases and expiration. Non-Functional Requirements (05:57): Qualities of the system like low latency on redirects, scalability targets, uniqueness of codes, and the choice between Consistency and Availability (CAP Theorem).
To solidify this, here is a text resource that provides a great checklist and example dialogue for requirement gathering.
Clarifying Requirements for a URL Shortener
The article 'Design Url Shortener' from AlgoMaster.io presents a detailed list of requirements. It's a useful reference to ensure you've considered all the key aspects.
Read 'Section 1. Clarifying Requirements'. Compare this list with what was discussed in the video. Notice the emphasis on quantifying scale ('10 million new URLs per day') and latency ('under 50ms').
For our design, let's consolidate the key requirements:
- Functional:
- Generate a unique short URL from a long URL.
- Redirect users from a short URL to the original long URL.
- Support optional custom aliases.
- Support link expiration.
- (Optional) Track basic click analytics.
- Non-Functional:
- Low Latency: Redirects must be very fast (e.g., < 100ms).
- High Availability: The service, especially redirection, must be highly available. We'll choose Availability over strong Consistency.
- Scalability: The system must handle a high volume of reads and a moderate volume of writes (a classic read-heavy system).
- Uniqueness: Short codes must be unique.
3. Step 2: Back-of-the-Envelope Estimation
Now that we have a scale in mind, let's do some quick calculations. This step is vital to justify your design choices later (e.g., "Do we need to shard the database?" "How much cache do we need?").
Back-of-the-Envelope Estimation for a URL Shortener
The AlgoMaster.io article provides clear, easy-to-follow estimations for traffic, storage, and short code length.
Read 'Section 2. Back-of-the-Envelope Estimation'. Focus on how the assumptions (10M writes/day, 100:1 read/write ratio) translate into: Queries Per Second (QPS) for reads and writes. Total Storage required over 5 years. The necessary length of the short code using Base62 encoding.
Key Takeaways from Estimation:
- Read-Heavy: Read QPS (~11,500) is vastly higher than write QPS (~115). This immediately tells us to optimize the read path aggressively.
- Manageable Storage: The total storage (~5.5 TB over 5 years) is significant but can be handled by modern database systems, possibly even on a single powerful instance initially, but sharding is a necessary consideration for scaling.
- Short Code Length: A 7-character code using Base62 provides trillions of possibilities, giving us plenty of runway.
4. Step 3: API Design
With requirements defined, we can design the contract for our service. A clean, RESTful API is expected.
Beginner System Design Interview: Design Bitly w/ a Ex-Meta Staff Engineer
Let's return to the 'Hello Interview' video to see how the functional requirements map directly to API endpoints.
Watch from 13:28 to 18:57. Note the two primary endpoints: POST /urls: To create a new short URL. GET /{short_code}: To handle the redirection. Pay attention to the discussion of the request body for creation and the importance of using the correct HTTP verb.
A crucial point in the redirection API is the choice of HTTP status code:
302 Found(Temporary Redirect): The browser will always check with your service for the destination URL. This is great for collecting analytics and allowing the destination to be updated, but it puts more load on your service.301 Moved Permanently: The browser will cache the redirect permanently. This is extremely fast for the user and reduces your server load, but you lose the ability to track clicks or change the destination.
For a service like Bitly that relies on analytics, 302 is the standard choice.
5. Step 4: High-Level Design
Now we can start drawing the architecture. We'll begin with a simple setup and evolve it based on our requirements.
Beginner System Design Interview: Design Bitly w/ a Ex-Meta Staff Engineer
This segment of the video walks through creating the initial high-level design, connecting a client, server, and database to fulfill the core functions.
Watch from 18:57 to 27:20. Follow the logic of starting with a simple client-server-database model and mapping the API flows onto it. The video also covers how to handle custom aliases and expiration checks within this basic design.
Based on our estimations, we know this is a read-heavy system. A common and effective pattern is to separate the read and write logic into different services. This allows them to be scaled independently.

6. Step 5: Deep Dive
This is where you demonstrate your depth as a senior engineer. We need to tackle the hardest parts of the design.
A. Unique URL Generation
This is the heart of the problem. How do we generate a unique, short, non-predictable code at scale? Let's explore the main strategies and their trade-offs.
Beginner System Design Interview: Design Bitly w/ a Ex-Meta Staff Engineer
The 'Hello Interview' video provides an excellent breakdown of different generation strategies, from naive to more robust.
Watch from 27:20 to 40:28. The video discusses three main approaches. Analyze the pros and cons of each: Random Number Generator (+ Base62): Simple, but what is the 'Birthday Paradox' and why does it lead to collisions? How do you handle collisions (check-then-write)? Hashing the Long URL: Why is this essentially the same as the random approach in terms of collision probability? Incrementing a Counter (+ Base62): This guarantees uniqueness. What are its downsides (predictability, single point of failure)?
The video introduces a great set of options. For a truly large-scale, distributed system, we need a solution that avoids the single-point-of-failure of a global counter while still guaranteeing uniqueness. This leads us to the industry-standard approach.
Unique URL Generation Strategies
The AlgoMaster.io article provides a superb deep dive into three generation strategies, culminating in the highly scalable distributed ID generator model.
Read 'Section 6.1 Unique URL Generation'. Focus on understanding the three approaches: Approach 1: Hashing + Encoding: Reinforces the video's points on collisions. Approach 2: Global Counter: Note the proposed solutions for its limitations (sharded counters, ID obfuscation). Approach 3: Distributed Unique ID Generator (Snowflake-style): This is the key takeaway. Understand how combining a timestamp, worker ID, and sequence number allows for decentralized, scalable, and k-sortable ID generation.
Recommendation for an Interview:
You should be able to discuss all three approaches. Start with the counter as the simplest, explain its flaws. Discuss hashing and its collision issues. Finally, present the distributed ID generator (Snowflake) as the most robust, scalable solution, demonstrating your understanding of distributed systems principles.
B. Scaling the System
With our components defined, how do we make them handle millions of users?
The LINK video we've been watching provides a great walkthrough of scaling each part of the system.
Beginner System Design Interview: Design Bitly w/ a Ex-Meta Staff Engineer
Let's look at how to scale the design to meet our non-functional requirements for latency and throughput.
Watch from 40:28 to 58:22. This long segment is packed with critical deep-dive topics: Low Latency on Redirects (40:28): How do database indexing and adding a cache (like Redis) drastically improve read performance? Scaling to 100M DAU (47:09): How do you scale the application servers horizontally? The rationale for splitting into read/write microservices. How do you scale the counter if you chose that approach (using a global counter service)? How do you scale the database (sharding, replicas)?
To tie everything together, here is a diagram of a more advanced, fully scaled-out architecture.

C. Database Choice: SQL vs. NoSQL
Your choice of database must be well-justified.
- The case for NoSQL (e.g., DynamoDB, Cassandra):
- The core operation is a key-value lookup (
short_code->long_url), which NoSQL databases excel at. - They are designed for massive horizontal scalability and high availability, aligning with our non-functional requirements.
- The core operation is a key-value lookup (
- The case for SQL (e.g., PostgreSQL, MySQL):
- The data has a predictable, fixed schema.
- ACID properties can be beneficial, especially for ensuring the uniqueness of custom aliases.
- With proper indexing and replicas, a SQL database can handle significant read traffic. The storage requirement (a few TB) is well within the capabilities of modern SQL systems.
In an interview, a good answer is to recommend a NoSQL database like DynamoDB for the core URL mapping due to the simple access pattern and extreme scalability requirements, but acknowledge that a sharded SQL database is also a viable option. You could also suggest using a separate database (SQL or a specialized analytics DB like ClickHouse) for complex analytics queries.
Conclusion
Congratulations! You've just walked through a complete design for a URL shortening service, from requirements to a scalable, distributed architecture.
Key Takeaways:
- Follow the Framework: A structured approach (Requirements -> Estimation -> API -> HLD -> Deep Dive) is key to success.
- It's a Read-Heavy System: The 100:1 read-to-write ratio dictates every major decision. The read path must be heavily optimized with caching (CDN, Redis) and fast lookups.
- ID Generation is Crucial: The trade-offs between counter-based, hash-based, and distributed ID generators are the core technical deep dive. For a senior role, being able to design a Snowflake-like system is a major plus.
- Justify Your Choices: Every decision, especially the database choice, must be backed by reasoning tied to the requirements and estimations.
Next Lesson Preview:
A public service like a URL shortener is a prime target for abuse. To protect our system from being overwhelmed, we need to implement rate limiting. In our next lesson, we will compare rate limiting algorithms (token bucket, leaky bucket, sliding window) and their trade-offs, a critical component you would add to the API Gateway or application services in this design.