Autocomplete & Typeahead
Also Known As
typeahead
search suggestions
prefix search
TL;DR
Showing relevant suggestions as the user types — requiring fast prefix search, debouncing, and careful UX to be helpful rather than distracting.
Explanation
Autocomplete strategies: prefix matching (startsWith), edge n-gram tokenisation (index every prefix), and completion suggesters (Elasticsearch's specialised structure). Performance: debounce input (wait 200-300ms after last keystroke before querying), cache recent queries, limit result count (5-10), and use a search engine not LIKE 'term%' SQL for large datasets. UX considerations: keyboard navigation, screen reader announcements (aria-live), and not autocompleting too aggressively.
Diagram
flowchart LR
USER[User types ph] --> DEBOUNCE[Debounce 150ms]
DEBOUNCE --> CACHE{Browser cache<br/>for this prefix?}
CACHE -->|hit| SHOW[Show suggestions instantly]
CACHE -->|miss| API[GET /autocomplete?q=ph]
API --> TRIE2[Server-side Trie<br/>or search engine prefix]
TRIE2 --> RANK[Rank by frequency<br/>personalisation]
RANK --> RESP[Top 5-10 suggestions<br/>highlight matched prefix]
RESP --> CACHE
RESP --> SHOW
style SHOW fill:#238636,color:#fff
style RANK fill:#1f6feb,color:#fff
style DEBOUNCE fill:#d29922,color:#fff
Common Misconception
✗ Autocomplete can use LIKE 'term%' SQL — LIKE prefix searches work for small tables; at scale, edge n-gram indexes or dedicated completion structures are required for sub-10ms response.
Why It Matters
Autocomplete is the most user-visible search feature — slow or irrelevant suggestions destroy the search experience; proper implementation (debouncing + correct indexing) makes it instant.
Common Mistakes
- No debounce — a query fires on every keystroke, overwhelming the server for fast typists.
- Not caching autocomplete results — the same prefix is often typed repeatedly; cache aggressively.
- Showing too many suggestions — 10+ results require scrolling; 5-7 is the usability sweet spot.
- Not handling 'no results' gracefully — showing an empty dropdown is confusing; hide it or show a fallback.
Code Examples
✗ Vulnerable
// No debounce — fires on every keystroke:
document.getElementById('search').addEventListener('input', async (e) => {
const results = await fetch('/api/suggest?q=' + e.target.value);
// 'P' → 'PH' → 'PHP' → 3 requests in 100ms, all potentially in-flight
});
✓ Fixed
// Debounced + cached:
const cache = new Map();
let timer;
document.getElementById('search').addEventListener('input', (e) => {
clearTimeout(timer);
const q = e.target.value.trim();
if (q.length < 2) return hideSuggestions();
timer = setTimeout(async () => {
if (cache.has(q)) return showSuggestions(cache.get(q));
const results = await fetch('/api/suggest?q=' + encodeURIComponent(q)).then(r => r.json());
cache.set(q, results); // Cache for session
showSuggestions(results);
}, 250); // 250ms debounce
});
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
22 Mar 2026
Views
37
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
No pings yesterday
Amazonbot 16
Perplexity 7
Google 6
Ahrefs 2
Unknown AI 2
Also referenced
How they use it
crawler 32
crawler_json 1
Related categories
⚡
DEV INTEL
Tools & Severity
🟡 Medium
⚙ Fix effort: Medium
⚡ Quick Fix
Debounce input by 300ms, use AbortController to cancel previous requests, and show a loading state — the PHP search endpoint should return results in <100ms using a full-text index
📦 Applies To
PHP 5.0+
web
🔗 Prerequisites
🔍 Detection Hints
Search request on every keypress without debounce; no abort of previous requests; LIKE %term% query without full-text index
Auto-detectable:
✗ No
laravel-debugbar
chrome-devtools
⚠ Related Problems
🤖 AI Agent
Confidence: Low
False Positives: High
✗ Manual fix
Fix: Medium
Context: File
Tests: Update