design
Practical resources about design for software engineers.
152 results
Patterns for Maintainable Code
Design patterns are not cookbook recipes — they are a shared vocabulary for discussing solutions to recurring problems. Knowing when to apply (and when to avoid) a pattern is a hallmark of senior engineering.
Browse our catalog of creational, structural, and behavioral patterns. Each entry includes a real-world scenario, UML diagrams, implementation in multiple languages, and a discussion of trade-offs. From Singleton to Outbox, find the right tool for your context.
Bridge Incompatible Interfaces with the Adapter Pattern
How to integrate legacy APIs, third-party libraries, and incompatible interfaces using object adapters, class adapters, and facade adapters in Java, TypeScript, and Python.
Scale Read and Write Workloads with CQRS
How to separate read and write models using Command Query Responsibility Segregation for optimized queries, event sourcing, and independent scaling of read and write paths.
Model Complex Business Domains with Domain-Driven Design
How to structure code around business concepts using bounded contexts, aggregates, entities, value objects, and domain events to manage complexity in large applications.
Create Objects Flexibly with the Factory Pattern
How to use factory methods, abstract factories, and dependency injection containers to decouple object creation from usage and improve testability.
Build Maintainable Applications with Hexagonal Architecture
How to structure applications using ports and adapters to isolate business logic from frameworks, databases, and external services for testability and flexibility.
Implement Reactive Systems with the Observer Pattern
How to build event-driven, reactive systems using the observer pattern with pub/sub, event emitters, and reactive streams in JavaScript, Java, and Python.
Ensure a Single Instance with the Singleton Pattern
How to guarantee exactly one instance of a class exists in an application using lazy initialization, thread-safe creation, and registry-based singletons.
Swap Algorithms at Runtime with the Strategy Pattern
How to encapsulate interchangeable algorithms and behaviors using the strategy pattern with dependency injection, function pointers, and lambda strategies in Java, TypeScript, and Python.
Pipes and Filters Pattern
Chain processing steps with independent filters connected by pipes. A pattern for data transformation pipelines where each step is reusable and composable.
Abstract Factory for Cross-Platform UI Component Families
Create families of related objects without specifying concrete classes, enabling platform-specific implementations that share a common interface
Abstract Factory Pattern
Create families of related objects without specifying concrete classes. A creational design pattern for consistent object families.
Active Record Pattern
Wrap a database table or view in a class where an instance is tied to a single row, and the class provides methods for CRUD operations directly on the object.
Adapter Pattern
Convert the interface of a class into another interface clients expect. A structural design pattern for interface compatibility.
Adapter Pattern for Integrating External REST APIs
Use the Adapter pattern to normalize responses from external REST APIs into a consistent internal model without leaking third-party formats into your domain
Aggregate Pattern
Encapsulate a cluster of domain objects treated as a single unit for data changes. An Aggregate Root controls access to its internal entities and value objects.
Ambassador Pattern for Resilient Remote Service Access
Add a local ambassador that handles retries, circuit breaking, and monitoring when calling remote services, keeping the client simple and the service logic pure
Back-Pressure Pattern
Prevent upstream systems from overwhelming downstream consumers by propagating flow-control signals backward through the pipeline, ensuring stable throughput under load.
Backend for Frontend (BFF) Pattern
Create dedicated backend services tailored to the specific needs of each frontend client type, aggregating downstream APIs and optimizing data shapes per platform.
Blackboard Pattern
A shared knowledge space where independent specialized modules collaborate to solve complex problems by contributing partial solutions.
Bridge Pattern
Decouple an abstraction from its implementation so both can vary independently. A structural design pattern for platform independence.
Bridge Pattern for Decoupling UI Components from Themes
Separate an abstraction from its implementation so both can vary independently using the Bridge pattern for pluggable UI themes and rendering engines
Builder Pattern
Construct complex objects step by step. A creational design pattern for readable, configurable object construction.
Builder Pattern for Complex Configuration Objects
Use the Builder pattern to construct complex configuration objects with optional parameters and sensible defaults without telescoping constructors
Business Delegate Pattern
Reduce coupling between presentation and business tiers by introducing an intermediary that handles lookup, creation, and invocation of business services.
Cache-Aside Pattern
Load data into the cache on demand from the backing store. A caching pattern that gives the application full control over what and when to cache.
Cache Invalidation Pattern
Strategies for keeping cached data fresh: TTL expiration, explicit invalidation, write-through, and event-driven cache eviction.
Cache Stampede Prevention Pattern
Prevent thundering herd cache misses with locks, single-flight, and early refresh strategies to protect the database from concurrent reloads.
Chain of Responsibility for Request Processing Middleware
Pass requests along a chain of handlers where each handler decides whether to process the request or pass it to the next handler in the pipeline
Chain of Responsibility Pattern
Pass requests along a chain of handlers until one handles it. A behavioral design pattern for decoupling senders and receivers.
Circuit Breaker Pattern
Prevent cascading failures by stopping requests to failing services. An architectural pattern for resilient distributed systems.
Claim Check Pattern
Store large payloads in external storage and pass only a lightweight reference token through the message bus, reducing broker load and preventing message size limits from being exceeded.
Command Pattern
Encapsulate a request as an object, letting you parameterize clients with queues, logs, and undoable operations. A behavioral design pattern.
Command Pattern with Undo/Redo in TypeScript
Implement the Command pattern to encapsulate requests as objects, enabling undo/redo operations, request queuing, and operation logging
Compensating Transaction Pattern
Undo the effects of a completed transaction by executing a counter-operation, enabling eventual consistency in long-running business processes across distributed services.
Composite Entity Pattern
Map a coarse-grained entity to multiple database tables by composing dependent objects, reducing the number of fine-grained remote calls in EJB and distributed systems.
Composite Pattern
Compose objects into tree structures to represent part-whole hierarchies. A structural design pattern for treating individual objects and compositions uniformly.
Composite Pattern for UI Component Trees in React
Use the Composite pattern to compose objects into tree structures, letting clients treat individual objects and compositions uniformly in UI component hierarchies
Content Delivery Network (CDN) Pattern
Distribute static and live content through geographically dispersed edge servers to reduce latency, improve availability, and offload origin infrastructure.
Context Object Pattern
Encapsulate state and services needed by multiple components into a single context object, reducing method signature bloat and decoupling code from specific environment details.
CQRS Pattern
Separate read and write operations into different models, optimizing each for their specific workload. A data pattern for scalable systems.
Data Access Object (DAO) Pattern
Abstract and encapsulate all access to a data source by exposing a clean interface while hiding persistence details from business logic.
Data Mapper Pattern
Separate in-memory domain objects from the database by delegating persistence to a dedicated mapper layer, keeping models framework-agnostic.
Database per Service Pattern
Give each microservice its own private database to ensure loose coupling, independent deployment, and technology heterogeneity across the application portfolio.
Decorator Pattern
Add new functionality to objects dynamically by wrapping them. A structural design pattern for flexible behavior extension.
Decorator Pattern for HTTP Request Pipelines
Use the Decorator pattern to compose cross-cutting concerns like logging, metrics, and retries into HTTP request pipelines without modifying core logic
Dependency Injection Pattern
Supply dependencies from outside rather than creating them internally. An architectural pattern for decoupled, testable code.
Dependency Injection Container in TypeScript
Build a lightweight DI container that resolves class dependencies automatically, enabling testable, loosely-coupled applications without frameworks like Angular or InversifyJS
Distributed Lock Pattern
Coordinate mutually exclusive access to shared resources across distributed nodes using a consensus-based lock service, preventing race conditions in scaled-out systems.
Domain Event Pattern
Capture and publish major occurrences within a domain model to decouple side effects from core business logic and enable reactive workflows.
Eager Loading Pattern
Load related data in a single query rather than multiple round-trips, preventing the N+1 problem and improving read performance.
Entity-Component-System (ECS) Pattern
Compose entities from pure data components and process them with systems, enabling high-performance and flexible game object architecture without deep inheritance.
Event Bus Pattern
Decouple components by routing events through a central bus. A behavioral pattern for loosely coupled communication between modules.
Event-Carried State Transfer Pattern
Replicate state changes across services by publishing events that carry the full updated entity state, enabling consumers to maintain their own local copies without querying the source.
Event Sourcing Pattern
Store the state of an application as a sequence of events rather than storing only the current state. An architectural pattern for audit-friendly systems.
Facade Pattern
Provide a simplified interface to a complex subsystem. A structural pattern that hides implementation details behind a clean API.
Factory Pattern
Create objects without specifying the exact class to instantiate. A creational design pattern for flexible object creation.
Flyweight Pattern
Share objects to support large numbers of fine-grained objects efficiently. A structural design pattern for memory optimization.
Flyweight Pattern for Efficient Large-Scale Object Sharing
Use the Flyweight pattern to minimize memory usage by sharing as much data as possible between similar objects, essential for rendering large datasets
Front Controller Pattern
Route all incoming requests through a single handler that dispatches to the appropriate page command, centralizing request processing and security.
Gatekeeper Pattern
Place a validation and security boundary at the edge of a system to inspect, sanitize, and authenticate all incoming requests before they reach internal services.
Graceful Degradation Pattern
Degrade functionality instead of failing when dependencies are unavailable. Serve partial results, cached data, or fallback features to keep users running.
Idempotent Consumer Pattern
Process messages from a queue exactly once regardless of duplicates by using idempotent operations, unique identifiers, and deduplication strategies at the consumer level.
Identity Map Pattern
Ensure each object is loaded only once per transaction by caching instances by their primary key, preventing duplicate in-memory representations of the same database row.
Inbox Pattern
Use a dedicated inbox table or queue to record incoming events or requests, ensuring reliable delivery, deduplication, and idempotent processing even when downstream systems fail.
Intercepting Filter Pattern
Compose cross-cutting concerns into a chain of pluggable filters that intercept requests and responses, enabling reusable preprocessing and postprocessing logic.
Interpreter Pattern
Define a representation for a language's grammar along with an interpreter that uses the representation to interpret sentences. A behavioral design pattern for mini-languages.
Interpreter Pattern for Domain-Specific Expression Languages
Build a language interpreter that evaluates expressions and rules by representing grammar as composable objects, useful for formulas, queries, and business rules
Iterator Pattern
Provide a way to access elements of a collection sequentially without exposing its underlying representation. A behavioral design pattern for traversal.
Iterator Pattern for Custom Collection Traversal in
Provide a way to access elements of an aggregate object sequentially without exposing its underlying representation using the Iterator pattern
Manager Pattern
Encapsulate lifecycle, coordination, and access control for a set of related objects through a dedicated manager class that centralizes operations and enforces invariants.
Marker Interface Pattern
Use empty interfaces as metadata tags to signal properties or capabilities at compile time and runtime, enabling type-safe checks without modifying class behavior.
Materialized View Pattern
Precompute and store expensive query results in a read-optimized cache to avoid repeated costly aggregation or joins across large datasets.
Mediator Pattern
Define an object that encapsulates how a set of objects interact. A behavioral design pattern for reducing chaotic dependencies.
Mediator Pattern for Loose Component Coupling in
Reduce chaotic dependencies between UI components by introducing a mediator that centralizes communication, preventing explicit references between peers
Memento Pattern
Capture and restore an object's internal state without violating encapsulation. A behavioral design pattern for undo/redo.
Memento Pattern for State Snapshot and Restoration
Capture and externalize an object's internal state without violating encapsulation, enabling undo, serialization, and state rollback in applications
Mixin Pattern
Add reusable behavior to classes without inheritance by composing methods from shared objects into a target class.
Model-View-Presenter (MVP) Pattern
Separate presentation logic from the view by introducing a presenter that intermediates between the model and a passive view, enabling testable UI code.
Model-View-ViewModel (MVVM) Pattern
Bind UI components declaratively to a ViewModel that exposes data and commands, enabling automatic synchronization between view and state.
Module Pattern
Encapsulate private state and behavior inside a self-contained unit with a public API. A structural pattern for organizing code into reusable, scope-safe modules.
Multiton Pattern
Manage a map of named singleton instances, providing controlled access to a finite set of shared objects identified by keys.
MVC Pattern in Modern Frontend Applications
Apply the Model-View-Controller pattern to React and Vue applications to separate data, UI, and interaction logic for maintainable component architecture
Null Object Pattern
Use a default object instead of null references to eliminate null checks and simplify client code. A behavioral pattern for safer defaults.
Object Pool Pattern
Reuse expensive objects instead of creating and destroying them repeatedly. A creational pattern for managing scarce resources efficiently.
Observer Pattern
Define a subscription mechanism to notify multiple objects about events. A behavioral design pattern for event-driven communication.
Outbox Pattern
Reliably publish domain events by persisting them in an outbox table within the same database transaction as the business operation.
Page Controller Pattern
Use a dedicated controller object for each logical page in a web application, handling the request and populating the view for that specific page.
Partial Class Pattern
Split a single class definition across multiple source files to separate auto-generated code from hand-written code, or to organize large classes by concern.
Plugin Pattern
Enable third-party extensions by defining extension points in a host system that loads and executes live external modules.
Priority Queue Pattern
Process tasks based on priority rather than arrival order, ensuring high-priority work gets resources before lower-priority tasks even if it arrived later.
Prototype Pattern
Create new objects by copying existing ones. A creational design pattern for cloning and object duplication.
Prototype Pattern for Object Cloning and Configuration
Create new objects by copying existing ones, allowing pre-configured templates and avoiding subclass explosion when object creation is expensive
Proxy Pattern
Provide a surrogate or placeholder for another object to control access to it. A structural design pattern for access control, lazy loading, and logging.
Proxy Pattern for API Response Caching
How to implement a caching proxy that intercepts API calls and stores responses to reduce latency and avoid redundant network requests
Queue-Based Load Leveling Pattern
Introduce a queue between task producers and consumers to smooth out traffic spikes, decouple components, and prevent downstream services from being overwhelmed by burst workloads.
Read-Through Cache Pattern
A transparent cache layer that intercepts read requests, fetches from the data source on miss, and populates the cache automatically.
Refresh-Ahead Cache Pattern
Proactively refresh cache entries before they expire to eliminate cache misses on hot keys and maintain consistent read latency.
Registry Pattern
Centralize access to shared services and objects via a lookup table. A structural pattern that decouples consumers from concrete implementations.
Repository Pattern with TypeScript Generics
Implement a type-safe repository pattern in TypeScript that decouples data access logic from domain services using generics and interfaces
Retry Pattern
Retry an operation that has failed with transient errors, using configurable strategies like fixed delay, exponential backoff, or circuit breaker integration.
Role Pattern
Assign dynamic roles to objects at runtime instead of hard-coding behavior in class hierarchies, enabling flexible identity changes without inheritance bloat.
Saga Pattern
Manage distributed transactions across multiple services by chaining local transactions with compensating actions for rollbacks. A microservices pattern.
Scheduler Agent Supervisor Pattern
Coordinate resilient job scheduling by separating scheduling logic from execution agents and adding a supervisor that monitors, restarts, and manages agent lifecycle.
Sequential Convoy Pattern
Preserve message ordering for related messages in a distributed system by grouping them into ordered sequences and processing them one at a time through a single consumer.
Serverless Event Sourcing Pattern
Store function state as an append-only event log so workflows can be replayed, audited, and recovered without a persistent database.
Serverless Fanout Pattern
Broadcast a single event to multiple independent consumers via SNS, EventBridge, or SQS so each consumer processes the event without coupling.
Serverless Function Composition Pattern
Chain serverless functions via Step Functions or orchestration layers to build multi-step workflows with retries, branching, and state management.
Serverless Throttling Pattern
Handle backpressure in serverless by using SQS, token buckets, and concurrency limits to protect downstream services from burst traffic.
Serverless Warm Pool Pattern
Keep Lambda functions warm by sending periodic ping events to reduce cold start latency for latency-sensitive workloads.
Sharding Pattern
Split a large dataset into smaller partitions (shards) distributed across multiple servers to improve growth, performance, and availability beyond single-node limits.
Singleton Pattern
Ensure a class has only one instance and provide global access to it. A creational design pattern for controlled object creation.
SOLID Principles in TypeScript with Practical Examples
Apply the five SOLID principles to TypeScript code to improve maintainability, testability, and reduce coupling in object-oriented designs
Specification Pattern
Encapsulate business rules for selecting objects as reusable, composable predicate objects that can be combined with logical operators.
State Pattern
Allow an object to alter its behavior when its internal state changes. A behavioral design pattern for finite state machines.
Static Content Hosting Pattern
Deploy static files to a dedicated content delivery network or object storage to offload origin servers, reduce latency, and improve availability for assets like images, CSS, and JavaScript.
Strategy Pattern
Define a family of algorithms, encapsulate each one, and make them interchangeable. A behavioral design pattern for flexible behavior selection.
Template Method Pattern
Define the skeleton of an algorithm in a base class, letting subclasses override specific steps without changing the algorithm's structure. A behavioral design pattern.
Throttling Pattern
Limit the rate at which a system processes requests or consumes resources to prevent overload, ensure fair usage, and maintain predictable performance under varying load.
Timeout Pattern
Prevent operations from hanging indefinitely by enforcing a maximum execution time. A resilience pattern for predictable response times.
Twin Pattern
Provide an alternative to multiple inheritance by linking two separate classes through mutual references, allowing them to delegate methods to each other as needed.
Two-Level Cache Pattern
Combine an L1 in-memory cache with an L2 distributed cache to reduce latency for hot keys while maintaining cache consistency across instances.
Type Object Pattern
Define game object types as runtime data rather than hard-coding them as classes, enabling designers to create new entity variants without recompiling the codebase.
Unit of Work Pattern
Track changes to in-memory objects during a business transaction and commit all updates atomically to the database, ensuring consistency.
Value Object Pattern
Model domain concepts by value rather than identity. An immutable object defined by its attributes, not by a unique ID.
Visitor Pattern
Represent an operation to be performed on elements of an object structure without changing the classes of the elements. A behavioral design pattern.
Visitor Pattern for Extensible Operations on Object
Separate algorithms from the objects they operate on, allowing new operations to be added without modifying existing element classes
Write-Behind Cache Pattern
Write to cache synchronously and persist to the database asynchronously for high-throughput write workloads with eventual consistency.
Write-Through Cache Pattern
Synchronously write to both cache and backing store so the cache always has the latest data without TTL-based invalidation.
GraphQL Connection Pagination Pattern
Implement Relay-style cursor-based pagination with edges, nodes, and pageInfo for stable GraphQL list queries.
GraphQL Federated Entity Pattern
Share entity types across federated GraphQL services so the gateway can resolve fields from multiple subgraphs transparently.
GraphQL Mutation Validation Pattern
Centralize input validation for GraphQL mutations using custom validators, schema directives, and structured error responses.
Feature Specification Template
A template for writing clear, actionable feature specifications that align engineering, product, and design before development begins.
User Story and Acceptance Criteria Template
A user story template that connects user needs to implementation with clear acceptance criteria, definition of done, and INVEST principles.
Clean Architecture
A practical guide to Uncle Bob's Clean Architecture: organize code into layers so that frameworks, UI, and databases are details, not dependencies.
CQRS — Command Query Responsibility Segregation
A complete guide to CQRS: separate read and write models to optimize performance, scalability, and team autonomy in complex domains.
Domain-Driven Design (DDD) — A Practical Guide
Learn DDD fundamentals: bounded contexts, entities, value objects, aggregates, and how to model complex business domains in code.
Event Sourcing — State as a Sequence of Events
A detailed analysis into Event Sourcing: persist state changes as events, reconstruct aggregates from history, and build audit trails by design.
Hexagonal Architecture — Ports, Adapters, and Testability
A complete guide to Hexagonal Architecture (Ports and Adapters): structure applications so domain logic is isolated from frameworks, databases, and external services.
Layered Architecture — N-Tier Explained
A practical guide to Layered (N-Tier) Architecture: separating presentation, business logic, and data layers with clear responsibilities and dependency rules.
Modular Monolith — A Pragmatic Architecture
A practical guide to Modular Monoliths: combine the simplicity of monoliths with the modularity of microservices through clear bounded contexts and strict module boundaries.
Onion Architecture — Dependency Inversion in Practice
A practical guide to Onion Architecture: organizing code around the domain model, enforcing dependency direction inward, and isolating infrastructure from business logic.
Software Architecture Guide
A guide to designing software architecture: monoliths vs microservices, layered architecture, data flow, and technology selection criteria.
Vertical Slice Architecture: Feature-First Organization
A practical guide to Vertical Slice Architecture: organizing code by feature instead of technical concern, reducing cross-layer navigation and improving cohesion.
Database Normalization — 1NF to 5NF Explained
A visual guide to database normalization: learn 1NF through 5NF with practical examples, when to apply each form, and how to balance normalization with performance.
Clean Code Principles: Writing Maintainable Software
A practical guide to clean code: meaningful names, short functions, DRY, SOLID foundations, and habits that make codebases easier to read and maintain.
What Works in Code Review — For Authors and Reviewers
A practical guide to useful code reviews: how to write reviewable code, give constructive feedback, and keep reviews fast and focused.
Practical Design Patterns Guide
A guide to selecting and applying the right design pattern for common software engineering problems.
SOLID Principles Explained with Examples
Learn the five SOLID principles with practical code examples: Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion.
Complete Guide to CSS Grid and Flexbox
Master modern CSS layout with Grid and Flexbox. Covers grid templates, areas, subgrid, responsive layouts, flexbox alignment, wrapping, gap, container queries, and when to use Grid vs Flexbox with practical examples and patterns.
Complete Guide to Mobile Responsive Design
Build responsive layouts that work on every device. Covers CSS Grid, Flexbox, container queries, fluid typography, mobile-first breakpoints, and responsive images.
Threat Modeling — A Practical Guide for Development Teams
A step-by-step guide to threat modeling: STRIDE, attack trees, data flow diagrams, and integrating security design review into your development process.
Test-Driven Development (TDD) — A Practical Workflow
Learn TDD step by step: write a failing test, make it pass, refactor. Red-Green-Refactor with real examples in Python, JavaScript, and Java.
No results found.