| Users | Changes in System |
|---|---|
| 100 users | Single adapter instance handles requests; simple direct calls; low latency. |
| 10,000 users | Multiple adapter instances needed; increased load on adaptee; possible latency increase. |
| 1,000,000 users | Adapters become bottleneck; need load balancing; adaptee service may need scaling; caching considered. |
| 100,000,000 users | Adapters fully distributed; sharding of adaptee services; asynchronous communication; heavy caching and CDN usage. |
Adapter pattern in LLD - Scalability & System Analysis
The adaptee service behind the adapter is the first bottleneck. As all adapter calls translate to adaptee calls, the adaptee's capacity limits overall throughput.
- Horizontal scaling: Add more adapter instances behind a load balancer to distribute client requests.
- Adaptee scaling: Scale the adaptee service horizontally or vertically to handle increased load.
- Caching: Cache adaptee responses in adapters or a shared cache to reduce repeated calls.
- Asynchronous processing: Use message queues to decouple adapters from adaptee for heavy workloads.
- Sharding: Partition adaptee data/services to reduce load per instance.
Assuming each adapter instance handles ~2000 concurrent requests:
- At 10,000 users: ~5 adapter instances needed.
- At 1,000,000 users: ~500 adapter instances; adaptee must handle ~1M QPS.
- Storage depends on caching size; e.g., 1MB cache per adapter instance = 500MB at 500 instances.
- Network bandwidth: 1M QPS * average 1KB request/response = ~1GB/s bandwidth needed.
Start by explaining the adapter's role as a translator between incompatible interfaces. Then discuss how scaling affects both the adapter and adaptee. Identify the adaptee as the bottleneck and propose solutions like horizontal scaling, caching, and asynchronous processing. Use concrete numbers to show understanding of capacity limits.
Your database handles 1000 QPS. Traffic grows 10x. What do you do first?
Answer: Add read replicas and implement caching to reduce direct database load before scaling vertically or sharding.
Practice
Adapter pattern in system design?Solution
Step 1: Understand the Adapter pattern role
The Adapter pattern acts as a bridge between two incompatible interfaces, allowing them to communicate.Step 2: Compare with other options
The other options describe different design goals unrelated to interface compatibility.Final Answer:
To allow incompatible interfaces to work together by converting one interface to another -> Option BQuick Check:
Adapter pattern = interface compatibility [OK]
- Confusing Adapter with Singleton or Factory patterns
- Thinking Adapter improves performance directly
- Assuming Adapter stores data
Solution
Step 1: Identify Adapter pattern structure
The Adapter class implements the TargetInterface and holds a reference to the Adaptee to delegate calls.Step 2: Analyze options
class Adapter implements TargetInterface { private Adaptee adaptee; } correctly shows Adapter implementing TargetInterface and containing Adaptee. The other options misuse inheritance or interfaces.Final Answer:
class Adapter implements TargetInterface { private Adaptee adaptee; } -> Option DQuick Check:
Adapter implements target and wraps adaptee [OK]
- Using inheritance incorrectly instead of composition
- Confusing which interface to implement
- Swapping adaptee and target roles
class Adaptee {
String specificRequest() { return "Adaptee response"; }
}
interface Target {
String request();
}
class Adapter implements Target {
private Adaptee adaptee = new Adaptee();
public String request() {
return adaptee.specificRequest();
}
}
public class Main {
public static void main(String[] args) {
Target target = new Adapter();
System.out.println(target.request());
}
}Solution
Step 1: Trace method calls in Adapter
The Adapter's request() calls adaptee.specificRequest(), which returns "Adaptee response".Step 2: Check main method output
Main creates Adapter as Target and prints target.request(), so output is "Adaptee response".Final Answer:
Adaptee response -> Option AQuick Check:
Adapter delegates request() to adaptee.specificRequest() [OK]
- Expecting 'Target response' instead of adaptee's
- Assuming compilation or runtime errors without cause
- Confusing method names
interface Target {
void request();
}
class Adaptee {
void specificRequest() { System.out.println("Adaptee called"); }
}
class Adapter implements Target {
Adaptee adaptee = new Adaptee();
public void request() {
specificRequest();
}
}Solution
Step 1: Review Adapter's request() method
Adapter calls specificRequest() directly, but specificRequest() belongs to Adaptee instance, so it should call adaptee.specificRequest().Step 2: Validate other options
Adaptee does not need to implement Target. Adapter implements Target correctly. Target interface method is correct.Final Answer:
Adapter calls specificRequest() without referencing adaptee instance -> Option AQuick Check:
Adapter must call adaptee.specificRequest() [OK]
- Calling adaptee methods without instance prefix
- Misusing inheritance instead of composition
- Changing Target interface unnecessarily
processLegacyPayment(), but the platform expects processPayment(). How should you apply the Adapter pattern to solve this?Solution
Step 1: Understand integration requirement
The platform expectsprocessPayment(), but legacy system only hasprocessLegacyPayment().Step 2: Apply Adapter pattern
Create an Adapter that implements the platform interface and inside calls legacy'sprocessLegacyPayment()to adapt calls without changing legacy code.Step 3: Evaluate other options
Modifying the legacy code is risky. Discarding the legacy system is costly. Using inheritance is not possible if the legacy system is not designed for it.Final Answer:
Create an Adapter class implementing the platform's payment interface and inside it call processLegacyPayment() of the legacy system -> Option CQuick Check:
Adapter wraps legacy method to match platform interface [OK]
- Changing legacy code directly
- Ignoring Adapter pattern benefits
- Trying inheritance when not supported
Ready to prove it?
Pass the test and this pattern moves unknown
