System Design

HLD Vs LLD | System Design Essentials

High-Level Design (HLD) vs Low-Level Design (LLD)

When building scalable and robust software systems, the design phase is critical. In system design interviews and real-world engineering, design is typically broken down into two distinct phases: High-Level Design (HLD) and Low-Level Design (LLD).

Understanding the difference between the two ensures that software is built logically, starting from the big picture down to the intricate technical details.


High-Level Design (HLD)

High-Level Design is all about the "Macro" view of the system. It defines the overall architecture, major components, and how they interact with each other.

Key Characteristics of HLD:

  • Focus: The overall system architecture, data flow, and scalability bottlenecks.
  • Audience: Architects, senior engineers, and stakeholders.
  • Output: System architecture diagrams, component interactions (APIs), database choices (SQL vs NoSQL), and infrastructure (Load Balancers, CDNs, Caches).
  • Details: Treats components as "black boxes" that communicate via defined interfaces (e.g., REST, gRPC, event queues).

HLD Example: Ride-Sharing App Architecture

Here is a typical High-Level Design diagram for a ride-sharing service like Uber:

                            +-------------------+
                            |    API Gateway    |
                            +---------+---------+
                                      |
          +---------------------------+---------------------------+
          |                           |                           |
+---------v---------+       +---------v---------+       +---------v---------+
|   User Service    |       |   Driver Service  |       |  Payment Service  |
+---------+---------+       +---------+---------+       +---------+---------+
          |                           |                           |
          +-------------+-------------+                           |
                        |                                         |
              +---------v---------+                     +---------v---------+
              |   Location Data   |                     | Transaction Data  |
              |  (Redis / Redis   |                     | (PostgreSQL / ACID|
              |   Geospatial)     |                     |    Compliant)     |
              +-------------------+                     +-------------------+

Notice how HLD tells us what components exist and where data lives, but not how they are programmed.


Low-Level Design (LLD)

Low-Level Design is the "Micro" view. It zooms into the black boxes defined in the HLD and explains exactly how they work internally.

Key Characteristics of LLD:

  • Focus: Internal logic, algorithms, data structures, object-oriented concepts, and database schemas.
  • Audience: Developers and engineers who will be writing the code.
  • Output: Class diagrams, sequence diagrams, detailed DB schemas, and specific algorithmic approaches.
  • Details: Highly specific. It involves choosing the right design patterns (e.g., Singleton, Strategy, Factory), defining proper exception handling, and ensuring thread safety.

LLD Example: Driver Service (TypeScript)

Let's zoom into the Driver Service from our HLD above. The LLD defines the actual classes, interfaces, and patterns used to implement it.

Here is an LLD code snippet demonstrating the Strategy Pattern for finding drivers:

// 1. Define the Core Interfaces
interface Location {
    lat: number;
    lng: number;
}

interface Driver {
    id: string;
    name: string;
    currentLocation: Location;
    status: 'AVAILABLE' | 'ON_TRIP' | 'OFFLINE';
}

// 2. Define a Strategy Interface for Matching Drivers
interface DriverMatchingStrategy {
    findBestDriver(userLocation: Location, activeDrivers: Driver[]): Driver | null;
}

// 3. Implement Specific Strategies
class ShortestDistanceStrategy implements DriverMatchingStrategy {
    findBestDriver(userLocation: Location, activeDrivers: Driver[]): Driver | null {
        // Algorithm to calculate Haversine distance and return the closest driver
        console.log("Using Shortest Distance Algorithmic Strategy");
        return activeDrivers[0]; // Simplified for example
    }
}

class HighestRatingStrategy implements DriverMatchingStrategy {
    findBestDriver(userLocation: Location, activeDrivers: Driver[]): Driver | null {
        // Algorithm to filter by rating, then distance
        console.log("Using Highest Rating Strategy");
        return activeDrivers[0]; 
    }
}

// 4. The Context Class (The Actual Service Controller)
class RideMatchingHub {
    private strategy: DriverMatchingStrategy;

    constructor(strategy: DriverMatchingStrategy) {
        this.strategy = strategy;
    }

    public requestRide(userLocation: Location, activeDrivers: Driver[]): void {
        const selectedDriver = this.strategy.findBestDriver(userLocation, activeDrivers);
        if (selectedDriver) {
            console.log(`Ride matched with driver: ${selectedDriver.name}`);
        } else {
            console.log("No drivers available.");
        }
    }
}

This structural depth—defining interfaces, separating concerns, and applying design patterns—is the essence of LLD.


Summary: HLD vs LLD

FeatureHigh-Level Design (HLD)Low-Level Design (LLD)
PerspectiveMacroscopic (System architecture)Microscopic (Component implementation)
Questions AnsweredWhat are the components?How do the components work?
Design ElementsLoad balancers, databases, microservicesClasses, methods, data structures, design patterns
PhaseComes first. Sets the foundation.Follows HLD. Prepares for actual coding.

Mastering both is essential for any senior software engineer. Watch the video above for a detailed visual breakdown and interview tips!