Design URL Shortener (TinyURL)
URL Shortener কেন শিখবো?
TinyURL, bit.ly — এই সিস্টেমগুলো দেখতে simple মনে হয়, কিন্তু এটা design করতে গেলে অনেক interesting problem আসে। Interview-তে এটা সবচেয়ে common system design question।
https://www.amazon.com/dp/B0893CFLMS/ref=sr_1_1?keywords=... এই long URL কে https://tinyurl.com/y4dz9b বানানো — এই simple কাজের পেছনে অনেক complexity।
📌 Core Problem
একটা long URL নিয়ে একটা unique short code generate করুন। সেই code দিয়ে request আসলে original URL-এ redirect করুন। এটাকে URL Redirection Service বলে।
কী কী লাগবে?
✅ Functional Requirements
- →Long URL দিলে short URL generate করবেন
- →Short URL click করলেন original URL-এ redirect হবে
- →User custom alias দিতে পারবেন (optional)
- →URL expiration time set করা যাবেন
- →Analytics: কতবার click হলো দেখা যাবেন
⚡ Non-Functional Requirements
- →High availability — 99.9% uptime
- →Low latency redirect — 100ms এর কম
- →Scalable — 100M+ URLs handle করবেন
- →Short URL predictable না হওয়া (security)
- →Durability — URL কখনো হারাবে না
💡 Interview Tip
Interview-তে সবার আগে Functional vs Non-functional requirements পরিষ্কার করুন। এটা দেখায় যে আপনি problem systematically ভাবুন।
Numbers এর হিসাব
System design-এ numbers জানা দরকার। এটা না জানলেন সঠিক architecture করা যায় না।
🔢 Calculation
Writes: 100M / 86400 ≈ 1,160 req/sec
Reads: 10B / 86400 ≈ 115,000 req/sec
Storage: প্রতি URL ~500 bytes → 100M × 500B × 365 days ≈ 18TB/year
Cache: Hot URLs top 20% → 20% of 10B reads = 2B → cache these
System এর Big Picture
এই system-এ দুটো main flow আছে: (1) URL creation flow এবং (2) URL redirect flow।
URL SHORTENER — SYSTEM ARCHITECTURE
📝 URL Creation Flow
User long URL পাঠায় → API Server short code generate করে → Database-এ save করে → Short URL return করে।
🔀 Redirect Flow
User short URL click করে → API Server cache check করে → Cache miss হলে DB থেকে নেয় → 301/302 redirect পাঠায়।
Core Components বিস্তারিত
🔑 Short Code Generation Algorithm
এটাই সবচেয়ে interesting part। Long URL → 6-7 character short code কীভাবে বানাবো?
| Approach | কীভাবে কাজ করে | Problem | Production Use? |
|---|---|---|---|
| Random String | 6 random chars generate করুন | Collision check দরকার, DB round trip | মাঝামাঝি |
| MD5/SHA256 Hash | URL hash করুন, first 7 chars নাও | Collision possible, predictable | সাধারণত না |
| Base62 Encoding | Auto-increment ID → Base62 convert | Sequential, predictable | কখনো কখনো |
| Snowflake ID + Base62 | Distributed unique ID → Base62 | Slightly complex setup | ✓ Best Practice |
💡 Base62 কী?
Base62 = 0-9 (10) + a-z (26) + A-Z (26) = 62 characters। 7 characters দিয়ে 62⁷ = 3.5 trillion unique URLs possible। TinyURL এবং bit.ly এই approach use করে।
# Base62 encoding for URL shortening
BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
def encode_base62(num: int) -> str:
"""Auto-increment ID কে Base62 string এ convert করুন"""
if num == 0:
return BASE62[0]
result = ""
while num > 0:
result = BASE62[num % 62] + result
num //= 62
return result.zfill(7) # always 7 chars
# Example: ID 125 → "0000020", ID 3521614606208 → "abcdefg"
def create_short_url(long_url: str, db, cache) -> str:
# 1. DB-তে save করুন, auto-increment ID পান
url_id = db.insert({"long_url": long_url, "created_at": now()})
# 2. ID কে Base62 encode করুন
short_code = encode_base62(url_id)
# 3. DB update করুন short_code দিয়ে
db.update(url_id, {"short_code": short_code})
# 4. Cache-এ রাখুন future reads এর জন্য
cache.set(short_code, long_url, ttl=86400)
return f"https://tinyurl.com/{short_code}"🔀 301 vs 302 Redirect — গুরুত্বপূর্ণ Trade-off
| Type | Meaning | Browser Cache? | Analytics? | Use Case |
|---|---|---|---|---|
| 301 Permanent | URL চিরতরে move হয়েছে | হ্যাঁ, cache করে | কম accurate | Server load কমাতে |
| 302 Temporary | এই moment এ redirect | না করে | Accurate tracking | Analytics দরকার হলে |
⚠️ Decision
Analytics চাইলে 302 use করুন — প্রতিটা click track হবে। Server load কমাতে চাইলে 301 — browser cache করে রাখবে। TinyURL analytics offer করে তাই 302।
কোন Database, কেন?
| Database | Pros | Cons | Fit? |
|---|---|---|---|
| MySQL (SQL) | ACID, familiar, strong consistency | Scaling কঠিন, single point | Okay for small |
| PostgreSQL | ACID, better performance | Horizontal scaling কঠিন | Medium scale |
| Cassandra (NoSQL) | Massive scale, fault tolerant | No ACID, complex queries কঠিন | ✓ Large scale |
| DynamoDB | Managed, auto-scale, low latency | Expensive, vendor lock-in | ✓ AWS setup |
Schema Design
CREATE TABLE urls (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
short_code VARCHAR(10) UNIQUE NOT NULL,
long_url TEXT NOT NULL,
user_id BIGINT, -- who created it
created_at TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP, -- NULL = never expires
click_count BIGINT DEFAULT 0
);
-- short_code এ index — সবচেয়ে বেশি query এখানে
CREATE INDEX idx_short_code ON urls (short_code);
-- Analytics table (separate)
CREATE TABLE url_clicks (
id BIGINT PRIMARY KEY,
short_code VARCHAR(10),
clicked_at TIMESTAMP,
ip_address VARCHAR(45),
user_agent TEXT
);💡 Cache Strategy
Redis use করুন hot URLs cache করতে। Top 20% URLs = 80% traffic (Pareto principle)। Redis এ TTL set করুন, LRU eviction policy। Cache hit rate 80%+ হওয়া উচিত।
Scale করার পরিকল্পনা
📈 Read Heavy System — Cache is King
URL Shortener 100:1 read/write ratio। মানে mostly read। তাই cache দিয়েই বেশিরভাগ load handle করা যায়।
Redis cache দিয়ে redirect latency 1-2ms এ নামানো যায়। Database-এ hit প্রায় শূন্যে নামবে।
Cache invalidation কঠিন। URL expire করলেন cache-ও clear করতে হবে। Stale data risk আছে।
Database read replicas দিয়ে read scale করা যায়। Write শুধু master-এ যাবেন।
Replication lag এর কারণে newly created URL কিছুক্ষণ read replica-তে না-ও থাকতে পারে।
🌍 Global Scale — CDN + Multiple Regions
| Problem | Solution | Result |
|---|---|---|
| High redirect latency globally | CDN edge servers এ popular URLs cache | Redirect 10ms এ নামে |
| Single region failure | Multi-region deployment (Active-Active) | 99.99% availability |
| DB write bottleneck | Sharding by short_code first char | Write throughput বাড়ে |
| Hot keys in cache | Consistent hashing + replica | Cache hotspot নেই |
🎯 Key Trade-off: Consistency vs Availability
URL shortener এ Eventual Consistency acceptable। নতুন URL তৈরি হলে 1-2 second পরে সব regions এ পানয়া গেলেই হবে। Strong consistency এর জন্য performance sacrifice করা worth না।
কোন Technology ব্যবহার করবো?
Backend
Database & Cache
Infrastructure & Analytics
| Component | Choice | Why? |
|---|---|---|
| API Language | Go | High concurrency, low latency, compiled language |
| Primary DB | MySQL + Replication | Familiar, ACID, strong ecosystem |
| Cache | Redis | In-memory, blazing fast, TTL support |
| Analytics | Kafka + ClickHouse | Real-time streaming + OLAP queries |
| CDN | CloudFront | Global edge, S3 integration |
Interview Tips ও Common Mistakes
Requirements Clarify করুন আগে
Directly design এ না গিয়ে জিজ্ঞেস করুন — custom alias দরকার? analytics চাই? expiration দরকার? কত users? এটাই interviewer দেখতে চায়।
Capacity Estimation দেখাও
100M daily URLs, 100:1 read/write ratio, 115K reads/sec — এই numbers মুখস্থ রাখুন এবং calculation করে দেখাও।
Base62 vs Hash — পার্থক্য জানেন
Hash collision possible। Base62 + auto-increment ID collision-free। Snowflake ID দিয়ে distributed unique ID generate করা best practice।
301 vs 302 Trade-off বলুন
এই question প্রায় সব interview তে আসে। 302 = analytics, 301 = server load কম। TinyURL analytics করে তাই 302।
Cache + DB Architecture বলুন
Read-heavy system। Redis cache → LRU eviction → DB read replica। Cache miss হলেই DB hit। Cache hit rate 80%+ target।
⚠️ Common Mistakes to Avoid
Mistake 1: MD5 hash directly use করা — collision possible, truncation আরও বেশি collision ঘটায়।
Mistake 2: Analytics এর জন্য 301 use করা — browser cache করে রাখে, server আর জানে না।
Mistake 3: Custom alias এর race condition ignore করা — DB UNIQUE constraint ছাড়া duplicate হবে।
Mistake 4: Cache invalidation না ভাবা — URL expire হলে Redis TTL + background cleanup দরকার।
💡 Bonus Points in Interview
Mention করুন: Eventual consistency acceptable কারণ URL shortener তে 1-2s lag কোনো problem না।
Mention করুন: Analytics async হওয়া উচিত (Kafka) — redirect path block করা উচিত না।
Mention করুন: Sharding strategy — short_code এর first char দিয়ে shard করা যায়।
SUMMARY — আজকে যা শিখলাম
| Concept | Decision | Why |
|---|---|---|
| Short Code Gen | Base62 + Auto-increment ID | Collision-free, compact |
| Redirect Type | 302 (analytics চাইলে) | Server-side tracking |
| Primary DB | MySQL → Cassandra (scale) | Start simple, scale later |
| Cache | Redis (LRU eviction) | 100:1 read ratio handle |
| Consistency | Eventual Consistency | Availability > Consistency |
| Analytics | Async via Kafka | Don't block redirect path |