Design a URL shortener service (high availability, 100M URLs, 10k reads/sec)
cs-sys-003
Your answer
Answer as you would in a real interview — explain your thinking, not just the conclusion.
Model answer
Clarify requirements: read-heavy (10:1 read/write), URL must be globally unique, short code ~7 chars, analytics (click counts), 99.99% uptime. Short code generation: use Base62 encoding of a distributed ID (Snowflake or ULID) rather than MD5 — avoids collisions deterministically. Storage: SQL for URL mapping (urlId PK, shortCode unique index, originalUrl, createdAt, userId); Redis for caching hot URLs with TTL. Redirect service: 301 (permanent) or 302 (temporary, enables analytics). 301 lets browsers cache; 302 hits the service every time — choose based on analytics needs. CDN edge cache in front for top 1% of URLs. For analytics, write click events to Kafka and process asynchronously to avoid blocking redirects. Horizontal scaling: stateless redirect servers behind a load balancer; DB read replicas. Capacity: 7-char Base62 = 62^7 = 3.5 trillion URLs.
Code example
// Short code generation using Base62 + Snowflake ID
public static class Base62
{
private const string Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public static string Encode(long id)
{
if (id == 0) return "0";
var sb = new StringBuilder();
while (id > 0)
{
sb.Insert(0, Chars[(int)(id % 62)]);
id /= 62;
}
return sb.ToString();
}
}
// Redirect endpoint
[HttpGet("/{code}")]
public async Task<IActionResult> Redirect(string code)
{
var url = await _cache.GetAsync(code) // Redis first
?? await _db.FindByCodeAsync(code); // then DB
if (url is null) return NotFound();
_ = _analytics.RecordClickAsync(code); // fire-and-forget
return RedirectPermanent(url.OriginalUrl);
}
Follow-up
How would you handle custom aliases (vanity URLs) and what are the collision risks?