Traffic baseline: normal day vs. celebrity hour
Assumptions:- ~1,000 clicks per short link created.
- 1,000,000 links created per day.
Even if a well-tuned Postgres instance might handle tens of thousands of reads/sec, this is a lot for a single DB host — and most of those reads are identical lookups that never change. For example, if 1,000 users click the same short URL, the DB returns the same long URL 1,000 times. That is wasteful.
Example mapping:
Solution: add a cache for hot keys
We should avoid sending a million identical queries to Postgres. Add a fast in-memory cache (for example, Redis) to serve hot keys in under a millisecond. Typical request flow for a redirect:- Client requests the short URL.
- Request hits the application server.
- Application server checks Redis:
- Cache hit: return the long URL immediately (no DB involved).
- Cache miss: read from Postgres once, write the mapping into Redis, return the long URL.
- Subsequent requests for the same short code are served from Redis.
Staleness concerns
A common cache problem is staleness: the cache can contain outdated data while the database has been updated (e.g., cache hasx = 7, DB has x = 9). That can cause incorrect responses.

In a URL shortener the mapping from short code to long URL is written once and never updated. That makes this workload ideal for aggressive caching: the cache will not serve incorrect data for these mappings.
Further optimizations: push hot keys closer to users
If Redis becomes a bottleneck or you want even lower latency, add additional layers:- Application-server local cache
- Each app server keeps a small in-process LRU cache (e.g., top few thousand links).
- Extremely hot links are served directly from app memory with minimal latency.

- Content Delivery Network (CDN)
- Place a CDN in front of the service so geographically nearby nodes can answer redirect requests.
- Regional CDN nodes absorb massive global spikes; on a cache miss they fall back to the origin.

Cache layers and responsibilities
Operational considerations
- TTL and eviction: set reasonable TTLs or rely on LRU eviction for Redis since mappings are immutable.
- Cache warming: pre-populate cache for anticipated viral links (if known).
- Monitoring & scaling: alert on cache miss rate, Redis CPU/network, and DB read rate to detect cascade failures early.
- Rate-limiting: protect origin DB with rate limits or request-shedding for extreme spikes.
Even with immutable short codes, ensure your CDN and caches honor expected TTLs or cache-control headers so you can retire or rotate links if necessary (for example, in legal takedown situations).
Putting it all together: recommended stack
- Use Redis as the primary cache for hot keys to avoid repeated Postgres reads.
- Keep a small LRU cache in each app server for the most popular short codes.
- Front the system with a CDN so regional requests are handled close to the user.