- 301 Moved Permanently — indicates the resource has moved permanently.
- 302 Found — typically used for temporary redirects.
Key consequences of choosing 301 vs 302
- 301 reduces server load and latency because browsers/intermediaries can cache the redirect and skip your service on subsequent clicks.
- 301 sacrifices visibility and control: analytics become unreliable because clicks may never reach your servers, and you may not be able to disable or change a short link once caches probe it.
- 302 keeps each click flowing through your service (better analytics, ability to disable links), but increases your server load and latency.
- Cache behavior is not guaranteed — control caching explicitly with response headers such as
Cache-Control,Expires, andPragmawhen required.

- Which component will break first?
- What can we afford to lose when components fail?
- Caching layer (e.g., Redis): speeds up reads dramatically. If the cache fails, reads fall back to the primary database and latency increases but correctness remains intact — the database is the source of truth. Explicitly note that the cache is a performance optimization, not durable storage.
- Mapping table durability: the mapping (short_code → long_url) is critical data. Losing rows means broken links and irrecoverable user impact.
- Counters/ID generators: any global counter used to create unique short codes must be monotonic and never produce duplicates after a crash. Duplicate codes would assign the same short URL to multiple destinations and break correctness.
Summary of end-to-end behavior (what to say in an interview)
- A user clicks a short link and the request hits our servers.
- Most requests should be served from cache to reduce latency; however, use
302(or other non-permanent redirects) if you need per-click analytics and the ability to disable links later. - The mapping table (short_code → long_url) is stored in a durable database (e.g., Postgres) with replicas and regular backups; it is the source of truth.
- Short codes are typically generated using a global counter plus Base62 encoding, or via hashing with deterministic collision handling. Ensure counters cannot repeat.
- Because the workload is read-heavy, scale reads with caching; writes are less frequent and therefore less of a scaling concern.
If per-click analytics or the ability to disable links after creation is required, prefer a temporary redirect (302) and prevent caching via headers (for example,
Cache-Control: no-store). Choose 301 only when mappings truly will not change and absolute performance is prioritized.- URL shorteners are typically read-heavy: caching is the main scaling lever.
- The mapping table is the durable source of truth; protect it with replication and backups.
- Generate unique short codes with a durable monotonic generator (global counter) combined with Base62 encoding; handle collisions if using hashes.
- Use
302when visibility and control are required; use301only when immutability and performance outweigh the need for analytics or revocation.
- HTTP Status Codes: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
- Caching best practices: https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching
- PostgreSQL replication and backups: https://www.postgresql.org/docs/current/high-availability.html