On this page · sections
01. Design Autocomplete / Search
Difficulty: Medium
Interview Focus: Async JavaScript · API Design · Caching · Performance
Interview Question
Design an autocomplete search component that shows relevant suggestions as the user types.
Requirements
Functional
- Show suggestions while typing
- Debounce API requests
- Support keyboard navigation
- Select a suggestion
- Handle loading, empty, and error states
- Support recent searches
Non-Functional
- Low latency
- Minimize API requests
- Prevent stale results
- Accessible
- Scalable
Solution
1. High-Level Architecture
User Input
↓
Debounce
↓
Cache Check
↓
Request Manager
↓
Search API
↓
Cache Result
↓
Render Suggestions2. Component Design
SearchAutocomplete
├── SearchInput
├── SuggestionList
│ └── SuggestionItem
└── SearchStateKeep input, suggestion rendering, and orchestration responsibilities separate.
3. Request Flow
User types "react"
↓
Wait 250ms
↓
Check Cache
┌───┴───┐
HIT MISS
↓ ↓
Render API Request
↓
Cancel old request
↓
Validate response
↓
Update Cache
↓
Render4. Debouncing
Instead of requesting on every keystroke:
r → re → rea → reac → react
↓
API RequestUse a 200–300ms debounce to reduce unnecessary requests.
5. Race Conditions
Problem:
Request A: "re" ─────────────→
Request B: "react" ───────→
B returns first ✓
A returns later ✗An older response must not overwrite newer results.
Solution — use:
AbortControllerto cancel obsolete requests- Request ID / version check to ignore stale responses
Cancellation improves efficiency; request IDs guarantee correctness.
6. Caching
Cache frequently requested queries:
"rea" → [...]
"react" → [...]
"redux" → [...]Benefits: faster suggestions, fewer API calls, lower server load.
For production, use TTL + LRU / size limits.
7. Accessibility
Use the accessible combobox pattern.
Support:
ArrowUp/ArrowDownEnterEscape- Focus stays on the input
- Screen readers
aria-expandedaria-activedescendant
8. Performance & Scale
Client: debounce · cancel obsolete requests · cache results · avoid unnecessary re-renders · lazy-load non-critical code.
Backend path:
Browser
↓
CDN / Edge
↓
API Gateway
↓
Search Service
↓
Search IndexUse caching, rate limiting, efficient search indexes, and horizontally scalable services.
Key Decisions
| Problem | Solution |
|---|---|
| Too many requests | Debounce |
| Obsolete requests | AbortController |
| Stale responses | Request ID |
| Repeated queries | Client cache |
| Large result sets | Virtualization if required |
| Keyboard access | Combobox pattern |
| API failure | Graceful error + retry |
Interview Q&A
Q1. Why debounce instead of throttle?
Autocomplete should wait until the user pauses typing. Debounce avoids unnecessary intermediate requests.
Q2. Why cancel requests?
A request for "re" is useless after the user types "react". Cancellation saves network and server work.
Q3. Is cancellation enough to solve race conditions?
No. A request may already have finished, or cancel may arrive too late. A request ID / version check ignores stale responses.
Q4. What would you cache?
Recent / frequent query results. Use normalized query keys with TTL and a max cache size.
Q5. How would you make it accessible?
ARIA combobox pattern — keyboard navigation, focus on the input, aria-activedescendant, screen-reader support.
Q6. How would you scale it?
Client + server caching, CDN / edge where appropriate, rate limiting, efficient search indexes, horizontal scale on the search service.
Interviewer Checklist
Async handling · API design · Race conditions · Caching · Performance · Accessibility · Scalability · Trade-offs