DEV Community

Cover image for System Design Learning Journey — Week 1: Scalability & URL Shortener
Majd-sufyan
Majd-sufyan

Posted on • Edited on

System Design Learning Journey — Week 1: Scalability & URL Shortener

Over the next 12 weeks, I’m focusing on one goal:

Becoming more confident in system design by going beyond theory and applying it in practice.

I’ll be documenting everything I learn — the concepts, the mistakes, and the design decisions.

Each week focuses on a different topic, with a real system to apply it.

Alt text

Week 1 — Scalability Basics & Designing a URL Shortener

Overview

In Week 1 of my system design learning plan, I focused on foundational scalability concepts and applied them by designing and implementing a URL shortener system.

The goal was not just to design a working system, but to:

  • Build intuition for data-intensive systems
  • Practice thinking in trade-offs
  • Connect

Key Learnings from Designing Data-Intensive Applications — Chapter 1

Data-Intensive vs Compute-Intensive Systems

Most modern applications are data-intensive, meaning the primary challenges are:

  • Volume of data
  • Speed of change
  • Access patterns (reads vs writes)

CPU is rarely the bottleneck.

This shifted my thinking from “what framework should I use?” to:

  • What data do I store?
  • How often is it accessed?
  • What guarantees does it need?

This mindset directly influenced how I designed the URL shortener.

Reliability, Scalability, and Maintainability

Chapter 1 emphasizes that failures are inevitable, but systems should be designed so faults don’t become failures.

Key takeaways:

  • Fault tolerance matters even for “simple” systems
  • Scalability is about how systems behave as load increases
  • Maintainability is critical because most software costs are long-term

These principles guided decisions like stateless services, caching, and asynchronous processing.

Load Balancing Fundamentals

A load balancer solves two core problems:

  1. Availability — no single server failure brings the system down
  2. Scalability — traffic can be distributed across multiple instances

Important insights:

  • Load balancers require stateless application servers
  • Distribution strategies (round-robin, least connections) affect latency
  • Health checks are essential to avoid routing traffic to failed instances

URL Shortener — System Design

Functional Requirements

  • Accept long URLs
  • Generate unique short keys
  • Redirect users to the original URL
  • Store mappings reliably

Non-Functional Requirements

  • Low latency (read-heavy workload)
  • High availability
  • Scalability
  • Fault tolerance
  • Optional analytics

High-Level Architecture

Figure 1: High-level request flow for URL creation, redirection, and analytics.

The system consists of:

  • Stateless API servers behind a load balancer
  • PostgreSQL for persistent storage
  • Redis for low-latency reads
  • Asynchronous analytics processing

Redirects are optimized for speed, while analytics are handled in the background.

Design Improvement: Asynchronous Analytics

Initial Approach (Synchronous)

Initially, redirect analytics were updated synchronously inside the redirect request:

val mapping = repository.findByShortUrl(shortUrl)
mapping.redirectCount +=1
repository.save(mapping)
return RedirectToOriginalResponse(mapping.originalUrl)

Enter fullscreen mode Exit fullscreen mode

Problem:

The user waits for a database write that provides no immediate value.

Timeline:

UserRequest
→DBRead(10ms)
→DBWrite(10ms)
→Response

Total ≈20ms
Enter fullscreen mode Exit fullscreen mode

Improved Approach (Asynchronous)

After revisiting DDIA’s discussion on latency and performance, I moved analytics updates to run asynchronously.

Now:

  • Redirect happens immediately
  • Analytics are processed in the background
  • Redirects remain fast even if analytics fail

Timeline:

User Request
→ DBRead (10ms)
→ Async event / queue
→ Response

User latency ≈10ms

Enter fullscreen mode Exit fullscreen mode

Why This Matters

This change:

  • Reduced redirect latency by ~50%
  • Improved resilience
  • Accepted eventual consistency where strict accuracy isn’t required

A key system design principle reinforced here:

Not all data needs the same consistency guarantees.

Implementation

The system was implemented using:

  • Kotlin + Spring Boot
  • PostgreSQL for persistence
  • Redis for caching
  • Asynchronous analytics processing

📌 Source code:

👉 https://github.com/Majd-sufian/12-week-System-Design-Learning-Plan/tree/main/url-shorten-project

Reflections

This week helped me:

  • Shift from component-level thinking to system behavior thinking
  • Make explicit design trade-offs
  • Connect theory (DDIA) to real implementation decisions

Designing even a “simple” system like a URL shortener revealed how quickly concerns like latency, fault tolerance, and scalability appear.

What’s Next — Week 2

  • Deeper dive into databases
  • Data modeling & indexing
  • Designing read-heavy systems under higher load

Top comments (0)