Read-heavy distributed URL shortening service with caching, replication, rate limiting, async analytics, and ID generation.
Start with one stateless-free monolith and one metadata database to validate the core create/redirect flow. Understand why a single node is simple but a single point of failure with no caching, protection, or scale-out.
What was missing: No edge protection, no cache, no replicas, no async pipeline, no observability — one service does everything.
Why that's risky: The bottleneck is the single monolith+DB: any spike, bug, or hardware failure takes the whole service down, and every redirect pays full DB latency.
What gets added: Nothing yet — this is the MVP baseline we will evolve.
Trade-offs: Trivial to build and operate, but not production-ready or globally fast.
Put a safe, fast global front door on the service: Geo-DNS for regional routing, a CDN for static/edge caching, a WAF/DDoS layer for protection, and an Anycast load balancer feeding an API Gateway and stateless app server.
What was missing: No global routing, no edge cache, no attack protection, and the app talked straight to the DB.
Why that's risky: The bottleneck was the exposed origin: distant users paid full RTT, repeat reads hammered the origin, and there was zero DDoS/WAF protection.
What gets added: Geo-DNS, CDN, WAF/DDoS edge, Anycast Load Balancer, an API Gateway and a stateless application server.
Trade-offs: More moving parts at the edge and a slightly longer request path in exchange for safety and global speed.
Make the application layer highly available and abuse-resistant: run stateless app servers behind API Gateways in two availability zones and add a Rate Limiter Service so a whole zone can fail and bots can't exhaust capacity.
What was missing: Only one zone of app compute and no request quotas — a zone outage meant a full outage, and bots could flood create/resolve.
Why that's risky: The bottleneck was single-zone app compute plus unthrottled traffic: one AZ failure or one abusive client could saturate everything.
What gets added: A second availability zone (API Gateway + stateless app servers) and a Rate Limiter Service enforcing per-IP/per-user quotas.
Trade-offs: More deployment and quota-tuning complexity for real HA and protection.
Break the monolith into independently scalable core services — URL Shortening (create), Redirection (resolve), User (auth), Analytics (stats) — so the hot read path and the write path scale separately and teams can own each service.
What was missing: The app servers still bundled create, resolve, auth and stats into one code path, so one concern's load or bug affected all of them.
Why that's risky: The bottleneck was coupling: the 90%-of-traffic resolve path shared capacity and deploys with rare, heavy create/auth work.
What gets added: Four dedicated core services (URL Shortening, Redirection, User, Analytics) called over gRPC, each scaled independently.
Trade-offs: More services and gRPC calls to operate and trace, in exchange for isolation and independent scaling.
Make redirects cache-first and scale reads globally: add a global Redis cluster in front of the Redirection Service, a session store to keep the app stateless, and multi-region read replicas so the write primary is never the read bottleneck.
What was missing: Every resolve still read a database, and all reads pointed at the single primary.
Why that's risky: The bottleneck was database reads on the hottest path: the primary couldn't serve 100k redirects/sec at <10ms, and popular links caused read storms.
What gets added: A global Redis cache (hot mappings), a Redis session store, and two multi-region read replicas fed by primary replication.
Trade-offs: Eventual consistency on replicas and cache-invalidation complexity in exchange for large read scale.
Decouple all heavy background work behind a Kafka event backbone with dedicated worker pools (redirection, analytics, cleanup, notification, export), plus a ClickHouse analytics store and object storage for backups/exports.
What was missing: Analytics, cleanup, notifications and exports still ran synchronously and shared the transactional DB, adding latency and contention.
Why that's risky: The bottleneck was doing durable, expensive work on the request path: click writes slowed redirects and a stalled job could back-pressure users.
What gets added: A Kafka cluster, five worker pools, a ClickHouse/Druid analytics DB, and S3/GCS object storage for backups and exports.
Trade-offs: Eventual consistency for analytics and more infrastructure to run for durability and throughput.
Add full observability across the multi-region platform — Prometheus metrics, ELK/OpenSearch logs, Jaeger traces, Alertmanager alerts and Grafana dashboards — so regressions are detected, diagnosed and paged before users feel them.
What was missing: The distributed system had no unified metrics, logs, traces, alerting or dashboards.
Why that's risky: The bottleneck was blindness: with many services across regions, a p99 regression or partial outage could go unnoticed until users complained.
What gets added: Prometheus, ELK/OpenSearch, Jaeger, Alertmanager and Grafana, wired to async telemetry from every component.
Trade-offs: More systems and signal to manage, plus alert-tuning to avoid noise.
Complete the production system by integrating external providers — SendGrid, Twilio, Cloudflare Turnstile, Cloudflare bot protection and Stripe — so comms, human-verification, edge security and billing are handled without building them in-house.
What was missing: No email/SMS delivery, no CAPTCHA/bot verification, and no billing integration.
Why that's risky: The bottleneck was missing business/security capabilities: no way to notify users, stop automated signups, or monetize — and building them in-house would be slow and risky.
What gets added: SendGrid, Twilio, Cloudflare Turnstile, Cloudflare bot protection and Stripe, called over REST from the relevant services/workers.
Trade-offs: Vendor dependencies, cost and data-sharing considerations in exchange for speed to market and robustness.
Introduce key salting for popular URLs, cache hot entries aggressively, and shard by hashed key prefix.
Eventual consistency for replicas is acceptable with primary writes and fallback when lag increases.
Use request coalescing, soft TTLs, and background refresh to avoid stampedes.
A single service and database reduce complexity and help validate core functionality quickly.
Rate limiting prevents abusive spikes and preserves capacity for legitimate traffic.
Async analytics decouple heavy writes from the request path and keep redirect latency low.
You're in the middle of an interview session. Leaving now will end your current attempt.
Explore concept overviews, real-system examples, key tradeoffs, and interview talking points for each roadmap section.
You've conquered this phase. These are the skills you now own: