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.
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:
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:
</svg>
This diagram illustrates the three main states of a circuit breaker:
Related Read:
For a deep dive into building robust, failure-resistant microservices in Spring Boot, check out Resilient Microservices Patterns.
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:
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:
Read More:
For a deeper dive—including code, diagrams, and use cases—see Event Sourcing Explained.
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:
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:
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:
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:
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:
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:
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:
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:
Related: For more details on the Cache-Aside pattern, see our API Optimization Techniques Guide.
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:
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:
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:
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!
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:
Learn about the top resilience patterns in microservices and how to implement them in Spring Boot. This guide covers circuit breakers, retries, timeouts, bulkheads, and more.
Learn the basics of gRPC and how to build gRPC microservices in Java and Spring Boot.

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