Top 15 System Design Patterns Every Senior Engineer Should Know

    Top 15 System Design Patterns Every Senior Engineer Should Know

    26/10/2025

    Introduction

    System design is the cornerstone of building scalable, reliable, and maintainable software. As senior engineers, a deep understanding of established design patterns is crucial for architecting robust systems. These patterns are reusable solutions to commonly occurring problems within a given context in software design. Let's dive into the top 15 system design patterns that every senior engineer should know.


    1. Publisher/Subscriber (Pub/Sub) Pattern

    The Publisher/Subscriber pattern is an asynchronous messaging pattern where senders of messages (publishers) do not program the messages to be sent directly to specific receivers (subscribers). Instead, publishers categorize published messages into classes without knowledge of which subscribers, if any, there may be. Similarly, subscribers express interest in one or more classes and only receive messages that are of interest, without knowledge of which publishers, if any, there are.

    Use Cases:

    • Decoupling microservices in a distributed system.
    • Real-time data streaming and event notifications.
    • Fan-out operations, where a single event needs to trigger multiple actions.

    Publisher/Subscriber Pattern


    2. Circuit Breaker Pattern

    The Circuit Breaker pattern is used to detect failures and prevents the application from trying to perform an action that is doomed to fail. This is essential for building resilient microservices that can handle partial failures gracefully. The circuit breaker acts as a proxy for operations that might fail. It monitors for failures and, after a certain threshold is reached, it "trips" and all further calls to the circuit breaker return with an error, without the protected operation being attempted at all.

    Use Cases:

    • Calling remote services over the network.
    • Operations that might time out or fail frequently.
    • Preventing cascading failures in a microservices architecture.
    Circuit Breaker in Electrical Circuit Service Client Circuit Breaker CLOSED Lights Outlets Appliance ! PROTECTED Normal Operation • Regular requests flow through the service • Dependent services operate normally • Circuit breaker maintains closed position
    Circuit Breaker Pattern in Microservices Flow Client ServiceA ServiceB Circuit Breaker Status CLOSED OPEN HALF-OPEN CLOSED Normal operation - Allowing all calls Preventing calls - Fast failing Testing recovery - Limited calls Normal operation - Allowing all calls Request 1 Call API (Circuit Closed) Success Response Request 2 Call API Failure (Circuit Opens) Request 3 Circuit Open - Fail Fast Immediate Error Wait recovery period Request 4 (Test) Test Call (Half-Open) Success (Circuit Closes) here
    </svg>
    

    This diagram illustrates the three main states of a circuit breaker:

    • Closed: All calls go through; failures are counted.
    • Open: Calls are blocked immediately after too many failures.
    • Half-Open: After a timeout, a few trial calls are allowed to check if the service has recovered. If successful, the breaker closes; if not, it reopens.

    Related Read:
    For a deep dive into building robust, failure-resistant microservices in Spring Boot, check out Resilient Microservices Patterns.


    3. Command Query Responsibility Segregation (CQRS)

    CQRS is a pattern that separates read and write operations for a data store. The model for updating data (the "command" model) is different from the model for reading data (the "query" model). This separation allows for independent scaling of read and write workloads and optimization of each model for its specific task.

    Use Cases:

    • High-performance applications with a high read-to-write ratio.
    • Complex domains where the read and write models are significantly different.
    • Systems that require different data consistency models for reads and writes.

    CQRS Pattern


    4. Event Sourcing Pattern

    With Event Sourcing, instead of storing just the current state of the data in a domain, you store a sequence of state-changing events. The application state is reconstructed by replaying the events. This provides a full audit log of all changes made to the system and can help with debugging and understanding complex domain behavior.

    Use Cases:

    • Financial systems requiring a full audit trail.
    • Collaborative applications where you need to resolve conflicting updates.
    • Systems where you need to analyze the history of state changes.

    Event Sourcing Pattern

    Read More:
    For a deeper dive—including code, diagrams, and use cases—see Event Sourcing Explained.


    5. Sidecar Pattern

    The Sidecar pattern deploys components of an application into a separate process or container to provide isolation and encapsulation. This pattern is often used in microservices architectures to attach "sidecars" to a service to provide platform features like logging, monitoring, and security.

    Use Cases:

    • Service mesh implementations (e.g., Istio, Linkerd).
    • Centralized logging and monitoring agents.
    • Adding HTTPS to a legacy service without changing its code.

    Sidecar Pattern


    6. API Gateway Pattern

    An API Gateway is a server that acts as a single entry point into the system. It is responsible for request routing, composition, and protocol translation. It can also be used to offload functionality from individual services, such as authentication, SSL termination, and rate limiting.

    Use Cases:

    • Microservices architectures with many services.
    • Providing a unified API for external clients.
    • Centralizing cross-cutting concerns like security and monitoring.

    API Gateway Pattern


    7. Strangler Fig Pattern

    The Strangler Fig pattern is a technique for incrementally migrating a legacy system. A new, modern system is built around the edges of the old system, gradually replacing its functionality over time. The old system is "strangled" by the new system until it can eventually be decommissioned.

    Use Cases:

    • Modernizing monolithic applications.
    • Reducing the risk of a "big bang" migration.
    • Incrementally replacing parts of a system with microservices.

    Strangler Fig Pattern


    8. Saga Pattern

    The Saga pattern is a way to manage data consistency across microservices in distributed transactions. A saga is a sequence of local transactions. Each local transaction updates the database and publishes a message or event to trigger the next local transaction in the saga. If a local transaction fails, the saga executes a series of compensating transactions that undo the changes that were made by the preceding local transactions.

    Use Cases:

    • Distributed transactions in a microservices architecture.
    • Long-running business processes that involve multiple services.
    • Systems that require eventual consistency.

    Saga Pattern


    9. Throttling (API Rate Limiting)

    Throttling is used to control the consumption of resources by an application or service. It limits the number of requests that a user can make in a given period. This helps to prevent abuse, manage costs, and ensure that the service remains available for all users.

    Use Cases:

    • Public APIs with usage quotas.
    • Preventing denial-of-service attacks.
    • Managing the load on downstream services.

    Throttling Pattern


    10. Sharding (Database Partitioning)

    Sharding is a type of database partitioning that separates very large databases into smaller, faster, more easily managed parts called data shards. Each shard is a separate database, and they can be spread across multiple machines. This allows for horizontal scaling of the database.

    Use Cases:

    • Very large databases that cannot fit on a single machine.
    • Applications with high read and write throughput.
    • Improving the performance and scalability of the data tier.

    Sharding Pattern


    11. Leader Election Pattern

    The Leader Election pattern is used to coordinate the actions of a collection of instances by electing one of them as the leader. The leader is responsible for managing the other instances and for coordinating their actions. This helps to prevent conflicts and to ensure that the instances work together in a consistent way.

    Use Cases:

    • Distributed systems that require a single coordinator.
    • Highly available systems where a new leader can be elected if the current one fails.
    • State management in a distributed environment.

    Leader Election Pattern


    12. Cache-Aside Pattern

    The Cache-Aside pattern (also known as lazy loading) is a caching strategy where the application is responsible for reading and writing data to the cache. When a request for data is made, the application first checks the cache. If the data is found (a cache hit), it is returned to the client. If the data is not in the cache (a cache miss), the application reads the data from the database, stores it in the cache, and then returns it to the client.

    Use Cases:

    • Read-heavy workloads.
    • Caching data that is not frequently updated.
    • Improving the performance of read operations.

    Cache-Aside Pattern

    Related: For more details on the Cache-Aside pattern, see our API Optimization Techniques Guide.


    13. Write-Ahead Log (WAL) Pattern

    The Write-Ahead Log (WAL) is a technique used to provide atomicity and durability in database systems. With WAL, all modifications are written to a log before they are applied. This ensures that even if the system crashes before the changes are fully written to the database, the changes can be recovered from the log.

    Use Cases:

    • Relational and NoSQL databases.
    • File systems.
    • Any system that requires durable and atomic transactions.

    Write-Ahead Log Pattern


    14. Bulkhead Pattern

    The Bulkhead pattern is a type of application design that is tolerant of failure. In a bulkhead architecture, elements of an application are isolated into pools so that if one fails, the others will continue to function. This pattern is analogous to the sectioned partitions (bulkheads) of a ship's hull.

    Use Cases:

    • Isolating critical services from non-critical ones.
    • Preventing a failure in one part of the system from bringing down the entire system.
    • Managing resources for different parts of an application.
    Bulkhead Pattern Flow ServiceA ServiceB ServiceC Bulkhead 1 Bulkhead 2 Call ServiceB Failure/Error Call ServiceC Success Each service call is isolated by its own bulkhead Error contained in Bulkhead 1 Other bulkheads remain unaffected Bulkhead 2 unaffected by Service B Service C Call Success Bulkhead isolates failures, preventing them from cascading across the system

    In this diagram, ServiceA calls both ServiceB and ServiceC through separate bulkheads. When ServiceB fails, the failure is contained within Bulkhead 1, allowing the call to ServiceC through Bulkhead 2 to proceed normally. This compartmentalization ensures that one failing service doesn't bring down the entire system.

    Key benefits of the Bulkhead pattern:

    • Failure isolation: Problems in one component don't affect others
    • Resource protection: Each service gets dedicated resources
    • Improved resilience: System continues functioning even when parts fail
    • Simplified debugging: Failures are contained to specific areas

    Implementation typically involves thread pools, connection pools, or semaphores to limit concurrent calls to specific services and ensure resources are properly allocated and protected.

    💡 **Looking to implement the Bulkhead pattern (and other resilience patterns) in Java with Spring? Check out the Resilient Microservices post for hands-on code examples (using Resilience4j), circuit breaker config, and real-world best practices!


    15. Ambassador Pattern

    The Ambassador pattern is useful for offloading common connectivity tasks such as monitoring, logging, routing, and security (like TLS) from your application's code. It can be thought of as an out-of-process proxy that is co-located with the client.

    Use Cases:

    • Offloading common connectivity tasks.
    • Abstracting away network-related concerns.
    • Providing a consistent interface to different services.

    Ambassador Pattern

    Summarise

    Transform Your Learning

    Get instant AI-powered summaries of YouTube videos and websites. Save time while enhancing your learning experience.

    Instant video summaries
    Smart insights extraction
    Channel tracking