| Users/Requests | What Changes? |
|---|---|
| 100 users | Few strategies implemented; simple context switching; low memory and CPU usage. |
| 10,000 users | More strategies added; increased context objects; moderate CPU usage; need for efficient strategy selection. |
| 1,000,000 users | High concurrency; many strategy instances; potential CPU bottleneck; need caching or pooling of strategies. |
| 100,000,000 users | Massive scale; strategy instantiation overhead critical; must optimize strategy reuse; consider distributed context handling. |
Strategy pattern in LLD - Scalability & System Analysis
Start learning this pattern below
Jump into concepts and practice - no test required
The first bottleneck is CPU and memory usage due to frequent creation and switching of strategy objects under high load. As user requests grow, the overhead of instantiating and managing many strategy instances can slow down the system.
- Object Pooling: Reuse strategy instances instead of creating new ones each time.
- Caching: Cache results of strategy computations when possible to avoid repeated work.
- Horizontal Scaling: Add more servers to distribute the load of strategy execution.
- Lazy Initialization: Instantiate strategies only when needed to save memory.
- Asynchronous Processing: Offload heavy strategy computations to background workers.
Assuming each user request triggers one strategy execution:
- At 1,000 QPS, CPU usage rises due to object creation and method calls.
- Memory usage grows with number of strategy instances; pooling reduces this.
- Network bandwidth impact is minimal as strategies run in-process.
- Storage is not significantly affected unless strategies cache data persistently.
When discussing scalability of the Strategy pattern, start by explaining how strategy objects are created and used. Then identify the overhead of instantiation and switching at scale. Propose concrete solutions like pooling and caching. Finally, mention horizontal scaling and asynchronous processing as ways to handle very high load.
Your database handles 1000 QPS. Traffic grows 10x. What do you do first?
Answer: Since the database is the bottleneck, first add read replicas or caching layers to reduce load. For the Strategy pattern, similarly, first optimize strategy instance reuse and caching before scaling servers.
Practice
Strategy pattern in system design?Solution
Step 1: Understand the Strategy pattern goal
The Strategy pattern is designed to let you swap algorithms or behaviors dynamically without changing the client code.Step 2: Compare options with pattern purpose
To allow selecting an algorithm's behavior at runtime without changing the client code correctly states this purpose. Options A and B describe Singleton pattern, and C describes Template Method pattern.Final Answer:
To allow selecting an algorithm's behavior at runtime without changing the client code -> Option BQuick Check:
Strategy pattern = runtime algorithm selection [OK]
- Confusing Strategy with Singleton pattern
- Thinking Strategy fixes algorithm steps
- Assuming Strategy creates single instances
Solution
Step 1: Identify the correct syntax for interface definition
In many object-oriented languages like Java or C#,interfacekeyword is used to define a Strategy interface with method signatures.Step 2: Evaluate options
interface Strategy { void execute(); } usesinterfacewith methodexecute(), which is correct. class Strategy { void execute(); } defines a class, not an interface. def Strategy(): pass is Python syntax but incomplete. struct Strategy { void execute(); } usesstructwhich is not typical for interfaces.Final Answer:
interface Strategy { void execute(); } -> Option CQuick Check:
Strategy interface = interface with method [OK]
- Using class instead of interface for Strategy
- Confusing struct with interface
- Using incomplete or wrong language syntax
class Context:
def __init__(self, strategy):
self.strategy = strategy
def execute(self):
return self.strategy.do_action()
class StrategyA:
def do_action(self):
return 'Action A'
class StrategyB:
def do_action(self):
return 'Action B'
context = Context(StrategyB())
print(context.execute())Solution
Step 1: Trace object creation and method calls
TheContextis created withStrategyB()instance. Callingcontext.execute()callsStrategyB.do_action().Step 2: Check StrategyB.do_action() return value
StrategyB.do_action()returns the string 'Action B', soprint(context.execute())outputs 'Action B'.Final Answer:
Action B -> Option AQuick Check:
Context with StrategyB = 'Action B' output [OK]
- Assuming default strategy is StrategyA
- Thinking method do_action is missing
- Confusing class and instance usage
class Context:
def __init__(self, strategy):
self.strategy = strategy
def execute(self):
return self.strategy.action()
class StrategyA:
def do_action(self):
return 'Action A'
context = Context(StrategyA())
print(context.execute())Solution
Step 1: Compare method names between Context and StrategyA
Context callsself.strategy.action(), but StrategyA definesdo_action(), notaction().Step 2: Identify mismatch causing error
This mismatch causes an AttributeError at runtime becauseaction()is undefined in StrategyA.Final Answer:
Context calls a method 'action' which does not exist in StrategyA -> Option AQuick Check:
Method name mismatch = runtime error [OK]
- Ignoring method name mismatch
- Assuming missing constructor causes error
- Thinking strategy should not be stored in context
Solution
Step 1: Understand Strategy pattern benefits in payment methods
Strategy pattern lets you define each payment method as a separate strategy class implementing a common interface.Step 2: Analyze how this affects system design
This design allows adding new payment methods easily without modifying existing code, and lets the system select payment method at runtime.Final Answer:
It allows adding new payment methods without changing existing code by defining each as a separate strategy -> Option DQuick Check:
Strategy pattern = easy extension and runtime choice [OK]
- Thinking Strategy forces shared implementation
- Believing all methods must be hardcoded together
- Assuming runtime selection is not possible
