Loading content...
Every LLD problem exists within a boundary. Understanding where that boundary lies—what's in scope and what isn't—is one of the most consequential decisions you'll make. Get it wrong, and you'll either design a system that's woefully incomplete or one that's overengineered beyond recognition.
The scope paradox:
In an interview, you have 45-60 minutes. You cannot design an entire e-commerce platform with inventory management, payment processing, recommendation engines, and fraud detection. Yet the problem statement may imply all of these. Your task is to identify the core scope that can be meaningfully designed in the available time while still demonstrating competence.
In real projects, the challenge is different but related: requirements documents often contain mountains of features. Your task is to identify what must be built now versus later, what the technical constraints permit, and how to create extensible designs that accommodate future scope.
Constraints are your friends:
Many engineers view constraints negatively—limitations on their creativity. In reality, constraints are design guides. They eliminate possibilities, reducing the solution space to something manageable. A system that must handle 'millions of users' demands different design choices than one for 'a single office.' A system with 'real-time' requirements differs from one with 'eventual consistency is acceptable.' These constraints don't limit you—they direct you.
By the end of this page, you will possess a systematic framework for identifying scope and constraints. You'll understand how to explicitly define system boundaries, recognize different types of constraints, negotiate scope appropriately, and document your decisions in a way that guides design and prevents drift.
Scope defines the boundaries of what your design will address. It answers the fundamental question: What problem are we solving, and what problems are we explicitly NOT solving?
In LLD specifically, scope operates at multiple levels:
The scoping spectrum:
Every LLD exercise falls somewhere on a spectrum from 'tightly scoped' to 'open-ended':
Tightly Scoped Problems:
Moderately Scoped Problems:
Open-Ended Problems:
Your first task is determining where on this spectrum your problem lies.
In interviews and in real projects, scope is negotiable. You're not expected to read the interviewer's mind about scope—you're expected to propose a reasonable scope, explain your rationale, and adjust based on feedback. The ability to scope well is itself an evaluated skill.
Constraints are the guardrails of your design. They come in several flavors, and missing any type leads to flawed designs.
Explicit Constraints:
These are directly stated in the problem. They're often numerical and precise:
Explicit constraints are relatively easy to handle—they're in the text, waiting to be extracted.
Implicit Constraints:
These are assumed based on domain knowledge or common sense:
Domain Constraints:
These come from the problem domain itself:
Technical Constraints:
These arise from the implementation environment:
| Constraint Type | Example | Design Impact |
|---|---|---|
| Explicit Numeric | 'Max 5 books per member' | Member.activeLoans ≤ 5; validation in borrow() |
| Explicit Business | 'Fine is $0.50 per day' | Fine calculation formula; Fine entity needed |
| Implicit Logic | Can't borrow already-borrowed book | BookCopy state check before loan creation |
| Implicit Temporal | Return date ≥ borrow date | Loan date validation; no time travel |
| Domain Knowledge | ISBN-13 format standard | Book.isbn validation; 13-digit format |
| Technical Stack | Using event-driven architecture | Events for state changes; eventual consistency |
| Performance | 'Real-time availability check' | Efficient lookups; possibly caching |
Engineers often assume implicit constraints are 'obvious' and don't need to be stated or designed for. This leads to bugs. Always make implicit constraints explicit in your design documentation. A constraint that isn't written down is a constraint that might be forgotten.
Use a systematic framework to define scope explicitly. This ensures nothing is missed and creates a shared understanding with stakeholders (or interviewers).
The In/Out/Later Framework:
For every feature or capability mentioned or implied, categorize it:
Example: Library Management System
Let's apply this to our running example:
SYSTEM: Library Management SystemDATE: [Current Date]SCOPE DECISION: Interview time-boxed (45 min LLD) ═══════════════════════════════════════════════════════════════════IN SCOPE (Will Design):═══════════════════════════════════════════════════════════════════Entities: ✓ Book (catalog information) ✓ BookCopy (physical copies) ✓ Member (library users) ✓ Loan (borrowing transactions) ✓ Fine (overdue penalties) ✓ Reservation (holds on books) Operations: ✓ Member borrowing a book ✓ Member returning a book ✓ Loan renewal (with reservation check) ✓ Fine calculation and payment ✓ Book reservation ✓ Basic search (title, author, ISBN) Business Rules: ✓ 5-book limit per member ✓ 14-day loan period ✓ Renewal rules (once, if not reserved) ✓ Fine calculation ($0.50/day) ═══════════════════════════════════════════════════════════════════OUT OF SCOPE (Will Not Design):═══════════════════════════════════════════════════════════════════Features: ✗ Multi-branch logistics (inter-branch transfers) ✗ Staff management and scheduling ✗ Acquisitions and vendor management ✗ Advanced search (full-text, recommendations) ✗ Notification system (email/SMS alerts) ✗ Report generation ✗ Member authentication/authorization details Technical: ✗ Database schema details ✗ API endpoint design ✗ Caching strategies ✗ Concurrency handling details Entities: ✗ Librarian (treat as system actor for now) ✗ Branch (single branch assumption) ✗ Publisher/Author as entities (attributes of Book) ═══════════════════════════════════════════════════════════════════FUTURE SCOPE (Design for Extension):═══════════════════════════════════════════════════════════════════ → Multi-branch support (design should not preclude) → Different user types (design with abstraction) → Payment integration (design fine with payment hook) → Notifications (design with event hooks) ═══════════════════════════════════════════════════════════════════KEY ASSUMPTIONS:═══════════════════════════════════════════════════════════════════ • Single-branch library (can extend later) • Book has unique ISBN; multiple copies exist • All operations are online (not batch) • Fine is auto-calculated at return timeNotice the 'Future Scope' section. Even things OUT of scope should influence your design slightly. You won't design multi-branch support, but you won't hard-code single-branch assumptions either. Good LLD anticipates future needs without implementing them.
Use a constraint extraction checklist to ensure you've captured all relevant constraints from the problem statement.
The Constraint Elicitation Checklist:
Applying the Checklist:
Let's apply each category to our library example:
| Category | Constraint Found | Design Impact |
|---|---|---|
| Cardinality | Member can have max 5 active loans | Loan creation validates count ≤ 5 |
| Cardinality | Book can have 1-N copies | Book has List<BookCopy>; copy can't exist without book |
| Value | Fine rate: $0.50 per day | Fine calculation uses this constant (configurable?) |
| Value | Loan period: 14 days | Due date = borrow date + 14 |
| State | BookCopy: Available → Borrowed → Available | BookCopy.status enum; transition methods |
| State | Loan: Active → Returned (or Overdue) | Loan.status enum; state machine |
| Temporal | Renewal allowed once | Loan.renewalCount ≤ 1 |
| Temporal | Renewal blocked if reserved | Check Reservation before renewal |
| Uniqueness | ISBN identifies a book | Book.isbn is unique key |
| Uniqueness | Member ID identifies member | Member.id is unique |
| Authorization | (Implied) Only member can borrow for themselves | Loan requires authenticated member |
| Computation | Fine = daysOverdue × rate | FineCalculator service or method |
| Existence | Loan requires existing Member and BookCopy | Foreign key / reference requirements |
| Consistency | Available copies = total - borrowed - reserved | Derived field or calculation |
Notice how every constraint has a 'Design Impact' column. This is the crucial connection: constraints aren't just documentation—they're design requirements. A constraint without a design accommodation is a bug waiting to happen.
One of the most nuanced aspects of scoping is distinguishing between what's explicitly in scope, what's implicitly expected, and what's genuinely out of scope.
Explicit Scope:
Directly stated in the problem. No ambiguity.
Implicit Scope:
Not stated, but any reasonable design would include it. Domain knowledge tells you it's necessary.
Gray Zone:
Features that reasonable engineers might disagree about. This is where you either ask or explicitly state your assumption.
The Assumption Declaration:
For gray zone items, explicitly state your assumption:
'The problem doesn't mention payment processing for fines. I'll assume fine collection is handled externally, and our system just tracks fine amounts owed. Is that acceptable, or should I include payment?'
This does three things:
Interviewers (and stakeholders) appreciate this pattern. It's exactly how senior engineers handle ambiguity in real projects.
The worst approach is silently assuming. If you're unsure whether something is in scope, say so: 'I'm assuming X is out of scope, but please let me know if you'd like me to include it.' This is professional, clear, and adjustable.
In interviews, time-boxing forces hard scope decisions. Here are strategies that work:
Strategy 1: MVP-First Scoping
Identify the Minimum Viable Product—the smallest set of features that makes the system coherent:
Strategy 2: Depth Over Breadth
It's better to deeply design 3 entities than shallowly sketch 10. Interviewers evaluate:
None of these can be demonstrated in a shallow sketch.
Strategy 3: Explicit Time Allocation
Verbally scope based on time:
'Given 45 minutes, I'll focus on the core booking flow, including User, Ride, Driver, and Matching logic. I'll defer payment, ratings, and real-time tracking to extensions. Does that work?'
This shows awareness of constraints and reasonable prioritization.
INTERVIEWER: "Design a ride-sharing service like Uber." CANDIDATE SCOPING RESPONSE: "That's a large system with many components. Given our time, let mepropose a scope: CORE SCOPE (I'll design in depth):• Rider requests a ride• System matches with nearby Driver• Driver accepts and completes trip• Core entities: Rider, Driver, Trip, Location, Matching SIMPLIFIED (I'll acknowledge but not detail):• Driver availability/status management• Pricing calculation (assume exists)• Rating system (mention as extension) OUT OF SCOPE (I'll omit):• Payment processing internals• Driver onboarding• Admin dashboards• Real-time location tracking infrastructure• Map/routing integration details I'll design the classes, relationships, and key methods for thecore ride-matching flow. If we have time, I can extend to ratingsor pricing. Does this scope work for you?" [INTERVIEWER ADJUSTS IF NEEDED]Strategy 4: Scope Negotiation as Skill Demonstration
Scoping well demonstrates the exact skills companies want:
Don't view scoping as a necessary evil before the 'real' design work. It IS part of the design work, and you're being evaluated on it.
Candidates who confidently scope, state their reasoning, and invite feedback almost always outperform those who either over-scope and run out of time, or under-scope and seem unaware of system complexity. Scoping is a leadership skill.
Constraints aren't just limitations—they're signposts pointing toward the right design. Each constraint suggests specific design decisions.
Constraint-Driven Design Decisions:
| Constraint | Design Implication | Example Approach |
|---|---|---|
| Max 5 items per user | Cardinality validation needed | Guard clause in add method; count check |
| Items have limited quantity | Concurrency handling needed | Optimistic locking or transaction |
| Multiple user types | Inheritance or composition | Abstract User base class; role-based |
| Audit trail required | Event sourcing or logging | Audit table; immutable records |
| Real-time updates | Push mechanism needed | Observer pattern; event bus |
| High read volume | Read optimization needed | Caching; read replicas |
| Complex pricing rules | Strategy pattern | PricingStrategy interface; runtime swap |
| State transitions matter | State pattern | Explicit state machine; transition methods |
The Constraint-to-Pattern Mapping:
Experienced engineers develop intuition for which patterns address which constraints:
Cardinality Constraints → Aggregate Roots When one entity 'controls' the count of another (parent controls how many children), the parent becomes an aggregate root managing that invariant.
Variability Constraints → Strategy/Factory When 'different types need different behavior' (pricing, validation, processing), the Strategy pattern allows runtime flexibility.
State Constraints → State Pattern/Enum When entities have explicit states with controlled transitions, either a formal State pattern or a well-managed enum is appropriate.
Temporal Constraints → Temporal Modeling When 'when' matters (effective dates, history), entities need timestamps, date ranges, or full temporal modeling.
Concurrency Constraints → Locking/Events When 'only one can succeed' (booking last seat), optimistic locking, pessimistic locking, or event-driven designs address the race condition.
1234567891011121314151617181920212223242526272829303132333435363738
CONSTRAINT: "A parking spot can only hold one vehicle at a time." DESIGN IMPLICATION:• ParkingSpot needs state (occupied/available)• State change must be atomic• Need to prevent double-booking RESULTING DESIGN: class ParkingSpot { id: SpotId status: SpotStatus // Available, Occupied, Maintenance vehicleId?: VehicleId // null if available // Atomic state change with validation assignVehicle(vehicle: Vehicle): Result<Ticket, SpotError> { if (this.status !== SpotStatus.Available) { return Err(SpotError.NotAvailable) } this.status = SpotStatus.Occupied this.vehicleId = vehicle.id return Ok(this.createTicket(vehicle)) } releaseVehicle(): Result<void, SpotError> { if (this.status !== SpotStatus.Occupied) { return Err(SpotError.NotOccupied) } this.status = SpotStatus.Available this.vehicleId = null return Ok() }} // The constraint (one vehicle per spot) drove:// • State enum with controlled transitions// • Validation before state change// • Clear error handling for violationsWhen unsure how to design something, look at the constraints. They'll tell you what the design MUST do. Working backward from constraints is often easier than inventing designs from scratch.
Scope decisions made but not documented are scope decisions waiting to be forgotten. Use structured documentation to capture and communicate scope.
The Scope Decision Record:
For each significant scope decision, document:
SCOPE DECISION RECORD: SDR-001 ═══════════════════════════════════════════════════════════════════DECISION: Payment processing is OUT of scope═══════════════════════════════════════════════════════════════════ RATIONALE:• Core problem is ride matching, not financial transactions• Payment is a generic problem (solved by Stripe, etc.)• Including payment would double design complexity• Time constraint: 45 minutes doesn't allow both IMPLICATIONS:• Trip entity will have 'fare' attribute but no payment flow• Will design PaymentService interface (for extension)• Fine/payment status tracking is simplified ALTERNATIVES CONSIDERED:• Include basic payment: Rejected (time, complexity)• Include payment interface only: Accepted (hook for extension) REVERSIBILITY:• Easy to extend: PaymentService interface exists• Design accommodates payment events ═══════════════════════════════════════════════════════════════════ SDR-002: Multi-region support OUT of scope RATIONALE:• Stated problem is "city-level" operation• Multi-region adds significant complexity (data partitioning)• Core matching logic doesn't change with region IMPLICATIONS:• Location model is simple (lat/long coordinates)• No region entity in initial design• Driver/Rider entities don't have region assignment DESIGN FOR EXTENSION:• Location could later include region_id• Matching service is abstracted (could become region-aware)Why Documentation Matters:
Prevents Drift — Halfway through design, you might unconsciously start adding out-of-scope features. The document refocuses you.
Enables Review — Others (interviewers, teammates) can evaluate whether scope decisions were reasonable.
Captures Rationale — Six months later, when someone asks 'why didn't we include X?', the answer is documented.
Shows Professionalism — Engineers who document scope demonstrate senior-level practice.
In Interviews:
You won't write formal documents, but you should verbally state and possibly whiteboard your scope boundaries before diving into class design. This serves the same purpose: clarity, agreement, and reference.
In an interview, spend 30 seconds writing your scope on the whiteboard. Something like: 'IN: User, Ride, Driver, Matching. OUT: Payment, Rating, Real-time tracking.' This small artifact anchors the entire session and prevents scope creep.
Identifying scope and constraints is the bridge between understanding the problem and designing the solution. Let's consolidate the key principles:
What's Next:
With scope and constraints identified, the next page addresses Clarifying Ambiguities—how to identify what's unclear, formulate clarifying questions, and systematically reduce uncertainty before design begins.
You now possess a systematic framework for identifying scope and constraints. This skill separates engineers who design what's needed from those who design what's imagined. Apply this to every LLD problem, and you'll never over-engineer or under-deliver again.