| Users / Scale | Small (100 users) | Medium (10K users) | Large (1M users) | Very Large (100M users) |
|---|---|---|---|---|
| Pattern Complexity | Simple patterns like Facade or Adapter for easy integration | Composite and Decorator to manage growing component complexity | Proxy and Flyweight to optimize resource use and access control | Combination of multiple patterns with distributed systems and microservices |
| System Components | Few components, direct connections | Multiple components, need for flexible composition | High number of components, need for resource sharing and control | Thousands of components, need for scalability and fault tolerance |
| Performance Needs | Low latency, simple calls | Moderate latency, some caching | High performance, resource optimization critical | Extreme performance, distributed caching, and load balancing |
| Maintenance | Easy to maintain, minimal abstraction | Moderate abstraction for flexibility | High abstraction to manage complexity | Very high abstraction, automated deployment and monitoring |
When to use which structural pattern in LLD - Scalability & System Analysis
At small scale, the bottleneck is usually the lack of flexibility in component integration, causing slow development or rigid code.
At medium scale, the bottleneck shifts to managing component complexity and communication overhead.
At large scale, resource usage and access control become bottlenecks, especially if patterns do not optimize sharing or proxying.
At very large scale, the bottleneck is system scalability and fault tolerance, requiring distributed pattern implementations and orchestration.
- Small Scale: Use simple structural patterns like Facade to simplify interfaces and Adapter to integrate external systems easily.
- Medium Scale: Employ Composite to build tree structures of components and Decorator to add responsibilities dynamically without changing code.
- Large Scale: Use Proxy to control access and Flyweight to share common data efficiently, reducing memory footprint.
- Very Large Scale: Combine multiple patterns with microservices architecture, distributed caching, and orchestration tools to handle complexity and scale.
Requests per second (RPS):
- Small: ~100-500 RPS, handled by single server with simple patterns.
- Medium: ~10K RPS, requires multiple servers and patterns supporting modularity.
- Large: ~100K RPS, needs resource optimization patterns and horizontal scaling.
- Very Large: ~1M+ RPS, demands distributed systems and complex pattern combinations.
Storage and Memory:
- Small: Minimal, simple object structures.
- Medium: Moderate, composite objects and decorators increase memory.
- Large: High, flyweight reduces memory but proxy adds overhead.
- Very Large: Very high, requires distributed caches and memory optimization.
Bandwidth:
- Small: Low, direct calls.
- Medium: Moderate, more component communication.
- Large: High, proxy and flyweight reduce bandwidth but increase complexity.
- Very Large: Very high, requires load balancing and CDN.
Start by explaining the system scale and complexity. Then describe which structural pattern fits best at each scale and why. Discuss bottlenecks and how patterns help solve them. Finally, mention trade-offs and how you would evolve the design as the system grows.
Your system uses a Composite pattern to manage UI components. Traffic grows 10x, and response time increases. What do you do first?
Answer: Analyze if the Composite structure causes deep recursion or heavy object creation. Introduce caching or flatten the component tree. Consider adding Flyweight to share common parts and reduce memory and processing overhead.
Practice
Solution
Step 1: Understand the problem context
Part-whole hierarchies like folders and files form tree structures where each node can be a composite or a leaf.Step 2: Match the pattern to the structure
The Composite pattern is designed to treat individual objects and compositions uniformly, perfect for tree-like structures.Final Answer:
Composite pattern -> Option BQuick Check:
Tree structures = Composite pattern [OK]
- Confusing Decorator with Composite
- Using Proxy for hierarchy management
- Choosing Facade for internal structure
Solution
Step 1: Identify the need to add features dynamically
When you want to add new behavior to objects at runtime without altering their class, you need a flexible pattern.Step 2: Select the pattern that wraps objects
The Decorator pattern wraps objects to add responsibilities dynamically, without changing the original class.Final Answer:
Decorator pattern -> Option DQuick Check:
Add features dynamically = Decorator [OK]
- Choosing Proxy instead of Decorator
- Using Facade to add features
- Confusing Composite with Decorator
class ResourceProxy {
constructor() {
this.resource = null;
}
access() {
if (!this.resource) {
this.resource = new RealResource();
}
return this.resource;
}
}Solution
Step 1: Analyze the code behavior
The code delays creating the real resource until it is accessed, controlling access and adding lazy loading.Step 2: Identify the matching pattern
This behavior matches the Proxy pattern, which controls access to another object and can add lazy initialization.Final Answer:
Proxy pattern -> Option AQuick Check:
Control access + lazy load = Proxy [OK]
- Confusing Proxy with Decorator
- Using Facade for access control
- Choosing Composite for resource control
class ComplexSystem {
operationA() {}
operationB() {}
operationC() {}
}
class SimpleInterface {
constructor() {
this.system = new ComplexSystem();
}
simpleOperation() {
this.system.operationA();
this.system.operationB();
this.system.operationC();
}
}
What is the likely mistake?Solution
Step 1: Understand Facade pattern purpose
Facade provides a simple interface hiding complex subsystem details from clients.Step 2: Identify the mistake in code usage
If clients still see complex calls, likely the ComplexSystem instance is exposed or clients bypass the Facade.Final Answer:
They did not hide the ComplexSystem instance properly -> Option AQuick Check:
Facade hides complexity = hide subsystem [OK]
- Confusing Proxy with Facade
- Exposing subsystem objects to clients
- Using Decorator to simplify interface
Solution
Step 1: Match patterns to requirements
Groups of shapes form tree structures best handled by Composite. Adding features dynamically fits Decorator. Controlling access fits Proxy.Step 2: Combine patterns correctly
Use Composite for shape groups, Decorator to add border color dynamically, and Proxy to control access to shapes.Final Answer:
Composite for groups, Decorator for features, Proxy for access control -> Option CQuick Check:
Groups=Composite, Features=Decorator, Access=Proxy [OK]
- Mixing Facade with group representation
- Using Proxy for adding features
- Confusing Decorator with access control
Ready to prove it?
Pass the test and this pattern moves unknown
