Requirements:
- Create a short code for a long URL.
- Redirect the visitor when they open the short link.
- Optional: custom aliases, expiry and basic click analytics.
Reads are far more common than writes, maybe 100 to 1. Redirects must be fast and highly available.
API: POST /urls returns the code. GET /{code} responds with a redirect.
ID generation: Take a unique number and encode it in base62 (a-z, A-Z, 0-9). 7 characters give about 3.5 trillion codes.
- Get the numbers from a counter. But avoid one single "hot" counter that every request hits. Instead, give each app instance a range of ids to hand out. Or use a Snowflake-style generator, which builds unique ids from time and machine number.
- Sequential codes are easy to guess. Shuffle or hide the pattern if that matters.
- Another option is to hash the URL and cut the hash short. This needs collision checks, because two URLs can produce the same code.
Storage: The data is a simple key-value lookup, code -> longUrl. A key-value store or a simple indexed table works well. It is easy to partition (split across machines) by code.
Redirect path: Check a cache (Redis) first. If the code is not there, read from the database. Popular links stay in the cache. Use 302 if you need to count every click. Use 301 if you want browsers to cache the redirect.
Analytics: Publish click events to a queue and add them up later, in the background. This keeps the redirect fast.
- The system is read-heavy, so it needs a cache and a fast redirect path.
- Make base62 codes from counter ranges or Snowflake ids.
- Avoid a single counter, and handle guessable codes and hash collisions.
- Use key-value storage partitioned by code.
- Choose between 301 and 302, and send analytics through a queue.