autocompletetype-aheadsearch suggestionssearch as you typecompletion suggester
TL;DR
Search suggestions shown as the user types — requiring prefix matching, typo tolerance, and sub-100ms response times to feel native, implemented via dedicated index structures or edge completion APIs.
Explanation
Autocomplete has stricter performance requirements than regular search — suggestions must appear within 50–100ms of each keystroke or users stop typing and wait, destroying the experience. Implementation approaches vary by scale: for small datasets (<10,000 items), a PHP endpoint filtering in-memory or using LIKE 'prefix%' queries is adequate. For larger datasets, a dedicated prefix index (MySQL prefix search with an indexed column, PostgreSQL pg_trgm with a GIN index, or Elasticsearch completion suggester) is required. Typo tolerance adds significant complexity — Elasticsearch's completion suggester supports fuzziness; for simple PHP implementations, trigram similarity indexes (pg_trgm) handle one or two character errors. Debouncing requests on the frontend (wait 150–200ms after the last keystroke before querying) reduces server load and prevents out-of-order response races.
Common Misconception
✗ Autocomplete can be implemented with a simple LIKE '%partial%' query. LIKE with a leading wildcard ('%partial%') cannot use a B-tree index and performs a full table scan. Autocomplete requires prefix matching (LIKE 'partial%' — note no leading wildcard) or trigram indexes for substring matching. The leading wildcard disables the index entirely, making the query unacceptably slow on any meaningful dataset.
Why It Matters
Autocomplete is one of the most user-visible search features and one of the most commonly implemented incorrectly in PHP applications. A typeahead that takes 500ms to respond feels broken — users perceive anything over 200ms as a lag. The implementation mistake of using LIKE '%partial%' works fine in development with 100 rows and fails silently in production with 100,000. Building autocomplete correctly from the start means: prefix-only matching, a proper index, debounced requests, and a response cache for common prefixes.
Common Mistakes
Using LIKE '%term%' instead of LIKE 'term%' — the leading wildcard disables all indexes.
Not debouncing keystrokes — firing a request on every keypress creates a thundering herd of requests and race conditions when responses arrive out of order.
Not caching popular prefix responses — the same two or three character prefixes generate the majority of autocomplete queries; cache them aggressively.
Returning too many suggestions — 5–8 suggestions is the usable maximum; returning 20 forces scrolling and degrades the experience.
Code Examples
✗ Vulnerable
// Full table scan — unusable at scale, SQL injection risk
$results = $pdo->query(
"SELECT name FROM products WHERE name LIKE '%{$q}%' LIMIT 10"
)->fetchAll();
// No index used, leading wildcard kills performance
✓ Fixed
// Prefix match — uses index, safe
$stmt = $pdo->prepare(
'SELECT id, name FROM products
WHERE name LIKE :prefix
ORDER BY popularity DESC
LIMIT 8'
);
$stmt->execute([':prefix' => $q . '%']); // note: prefix%, not %prefix%
$results = $stmt->fetchAll();
// With Redis cache for hot prefixes
$cacheKey = 'autocomplete:' . strtolower(substr($q, 0, 3));
$cached = $redis->get($cacheKey);
if ($cached) return json_decode($cached);
// ... query and cache with 60s TTL