Find the Bugs in an AI-Generated URL Shortener
MicrosoftSoftware Engineer · Technical ScreenLast updated
Tests code review, debugging, and refactoring skills by identifying flaws in an AI-generated in-memory URL shortener and implementing a robust, thread-safe replacement.
Problem Statement
You are reviewing a teammate's pull request containing an AI-generated prototype for an in-memory URL shortener service. The prototype has multiple functional and non-functional flaws:
import hashlib
class BadURLShortener:
def __init__(self):
self.url_map = {} # short -> long
self.reverse_map = {} # long -> short
def shorten(self, original_url):
if original_url in self.reverse_map:
return self.reverse_map[original_url]
# Generate 6-char hash token
token = hashlib.md5(original_url.encode()).hexdigest()[:6]
# Save mappings
self.url_map[token] = original_url
self.reverse_map[original_url] = token
return "http://short.ly/" + token
def resolve(self, short_url):
token = short_url.split("/")[-1]
return self.url_map[token]
Task
- Identify the bugs and design flaws in
BadURLShortener(e.g., hash collisions, unhandled misses, lack of thread safety, and URL validation). - Implement a production-grade class
URLShortenerthat addresses these issues.
Requirements & Interface
class URLShortener:
def __init__(self, base_url: str = "http://short.ly/"):
pass
def shorten(self, original_url: str) -> str:
"""Shortens a valid URL. Returns existing short URL if already registered.
Raises ValueError if original_url is empty or not a valid HTTP/HTTPS URL.
"""
pass
def resolve(self, short_url: str) -> str | None:
"""Resolves a short URL to the original URL. Returns None if not found."""
pass
Constraints
- Generated short tokens must be alphanumeric strings between 6 and 8 characters.
- Hash collisions must be handled cleanly without overwriting existing mappings.
- The class must be thread-safe for concurrent calls to
shortenandresolve. - Valid URLs must start with
http://orhttps://and have a non-empty host.
Example
shortener = URLShortener()
# Shorten new URL
s1 = shortener.shorten("https://www.example.com/very/long/path")
# e.g., "http://short.ly/aB3x9z"
# Idempotency check
s2 = shortener.shorten("https://www.example.com/very/long/path")
assert s1 == s2
# Resolution
assert shortener.resolve(s1) == "https://www.example.com/very/long/path"
assert shortener.resolve("http://short.ly/nonexistent") is None
Hints
Hint 1
Look at what happens when two different original URLs produce the same 6-character prefix under MD5: BadURLShortener blindly overwrites the existing entry.
Hint 2
Notice the missing error handling in resolve: accessing self.url_map[token] directly raises an unhandled KeyError instead of returning a predictable result or None.
Hint 3
Consider multi-threaded environments: Python dictionaries are individually thread-safe for single atomic operations, but read-then-write check sequences create race conditions without explicit locking.
Follow-up questions
- How would you support URL expiration (TTL) without degrading lookup performance?
- If this service moves from single-process memory to a distributed system, how would you generate non-colliding IDs across multiple worker nodes?
- What counter-strategies would you use to prevent denial-of-service via memory exhaustion if malicious clients submit billions of unique junk URLs?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.