# System Design: [Search autocomplete name]

> Reference design for search typeahead (autocomplete): as the user types, the
> service returns the most useful completions for the prefix within tens of
> milliseconds. It covers prefix indexes (trie, finite state transducer, edge
> n-grams), ranking by popularity and recency, the data pipeline from query
> logs, edge caching, the latency budget, personalisation and abuse filtering.
> It follows the structure of the System Design Document template and is
> pre-filled with a worked design to adapt. Values marked *Example* are
> assumptions: replace them and recompute.

<!--
Guidance: How to use this template
- Start from the latency budget (section 8). Typeahead that arrives after the
  next keystroke is useless, so every design choice must fit inside it.
- Size the index from your real query log (distinct queries above a
  frequency threshold), not from the raw log volume.
- Decide early what must never be suggested (7.6). Filtering is a product
  and policy decision as much as an engineering one.
- Personalisation adds privacy obligations; record retention and opt-out in
  section 9.2.
-->

## Document control

<!-- Guidance: A design is a proposal until it is approved; record who decided and when. -->

| Field | Value |
|---|---|
| Document ID | [SDD-AC-001] |
| System / feature | [Search suggestions] |
| Version | [0.1] |
| Status | [Draft / In review / Approved / Implemented / Superseded] |
| Author(s) | [@author] |
| Reviewers | [@reviewer-1], [@reviewer-2] |
| Last updated | YYYY-MM-DD |
| Related | [Search PRD], [Content policy for suggestions], [Privacy review] |

### Approvals

| Role | Name | Decision | Date |
|---|---|---|---|
| Tech lead | [@name] | [Approved / Changes requested] | YYYY-MM-DD |
| Staff / principal engineer | [@name] | [Decision] | YYYY-MM-DD |
| SRE / operations | [@name] | [Decision] | YYYY-MM-DD |
| Trust and safety / policy | [@name] | [Decision] | YYYY-MM-DD |
| Privacy | [@name] | [Decision] | YYYY-MM-DD |

## Revision history

<!-- Guidance: Note what changed in the design, not the wording. -->

| Version | Date | Author | Change summary |
|---|---|---|---|
| 0.1 | YYYY-MM-DD | [@name] | First draft for design review |
| 0.2 | YYYY-MM-DD | [@name] | *Example:* Added trending layer with 5-minute windows |
| 0.3 | YYYY-MM-DD | [@name] | *Example:* Moved personal history to the device by default |
| 1.0 | YYYY-MM-DD | [@name] | *Example:* Approved |

## Contents

<!-- Guidance: Keep aligned with the headings. -->

1. [Overview](#1-overview)
2. [Requirements](#2-requirements)
3. [Capacity estimation](#3-capacity-estimation)
4. [API design](#4-api-design)
5. [Data model](#5-data-model)
6. [High-level design](#6-high-level-design)
7. [Detailed design](#7-detailed-design)
8. [Scalability and performance](#8-scalability-and-performance)
9. [Reliability, security and operations](#9-reliability-security-and-operations)
10. [Trade-offs and alternatives](#10-trade-offs-and-alternatives)
11. [Delivery plan and risks](#11-delivery-plan-and-risks)
12. [Appendices](#12-appendices)

## 1. Overview

<!-- Guidance: One page that a busy reviewer can read alone: problem, proposed solution in a paragraph, and the decisions that need their attention. -->

### 1.1 Problem statement

[*Example:* Today suggestions come from a `LIKE 'prefix%'` query on the
product database. p99 is 380 ms, suggestions are alphabetical rather than
useful, breaking news terms take a day to appear, and last month an offensive
suggestion was screenshotted and shared widely.]

### 1.2 Proposed solution

[*Example:* An offline pipeline aggregates anonymised query logs hourly into
scored suggestions, filters them against policy lists, and builds an
immutable in-memory prefix index (a trie with the top completions cached at
each node). Suggest servers load the index and answer prefix requests in
under 5 ms. A streaming layer adds trending queries within minutes. Responses
for short, popular prefixes are cached at the CDN edge for 5 minutes. Personal
recent searches are blended in on the client from local history.]

### 1.3 Decisions requested from reviewers

| ID | Question | Recommended option | Section |
|---|---|---|---|
| Q-01 | *Example:* Trie with top-k per node, FST, or search-engine edge n-grams? | Trie with top-k per node | 7.1, 10 |
| Q-02 | *Example:* How fresh must suggestions be? | Hourly base index + 5-minute trending layer | 7.3 |
| Q-03 | *Example:* Server-side personal history? | No by default; device-local history, opt-in sync | 7.5 |
| Q-04 | *Example:* Cache at edge for which prefixes? | Length 1 to 3, non-personalised responses only | 7.4 |
| [Q-nn] | [Question] | [Option] | [Section] |

## 2. Requirements

<!-- Guidance: Functional requirements describe behaviour; non-functional requirements describe qualities with numbers. Mark what is out of scope so nobody designs for it. -->

### 2.1 Functional requirements

| ID | Requirement | Priority |
|---|---|---|
| FR-01 | *Example:* Return up to 10 completions for a prefix, ranked by usefulness | Must |
| FR-02 | *Example:* Support per-locale suggestions (language and market) | Must |
| FR-03 | *Example:* Reflect trending queries within 15 minutes | Should |
| FR-04 | *Example:* Never suggest terms on the policy blocklist | Must |
| FR-05 | *Example:* Blend the user's recent searches at the top, removable by the user | Should |
| FR-06 | *Example:* Tolerate one typo for prefixes of 4+ characters | Could |
| FR-07 | *Example:* Remove a reported suggestion globally within 10 minutes | Must |
| [FR-nn] | [Requirement] | [Must / Should / Could] |

### 2.2 Non-functional requirements

| ID | Quality | Target | Measured as |
|---|---|---|---|
| NFR-01 | Latency | *Example:* Server p99 at or below 20 ms; perceived p95 at or below 100 ms | Server metrics, client RUM |
| NFR-02 | Availability | *Example:* 99.9%; search must work without suggestions | Synthetic checks |
| NFR-03 | Freshness | *Example:* Base index at most 2 h old; trending at most 15 min | Index build timestamp |
| NFR-04 | Safety | *Example:* Zero blocklisted suggestions served | Audit sampling of served suggestions |
| NFR-05 | Privacy | *Example:* No suggestion derived from fewer than 50 distinct users | Pipeline threshold test |
| [NFR-nn] | [Quality] | [Target] | [Measurement] |

### 2.3 Out of scope

- [*Example:* the search results page itself]
- [*Example:* rich entity cards in the dropdown]
- [*Example:* voice query suggestions]
- [Item deferred, with the release that will take it]

## 3. Capacity estimation

<!-- Guidance: Back-of-the-envelope numbers decide the shape of the design. Show inputs, formulas and results; round generously and say which way you rounded. -->

### 3.1 Assumptions

| Input | Symbol | Value | Source |
|---|---|---|---|
| Daily active searchers | $U$ | *Example:* 100 million | Analytics |
| Searches per user per day | $q$ | *Example:* 5 | Analytics |
| Suggest requests per search after 100 ms debounce | $r$ | *Example:* 4 | Client telemetry |
| Peak to average factor | $k$ | *Example:* 3 | Traffic history |
| Edge cache hit ratio | $h$ | *Example:* 60% | Pilot measurement |
| Distinct suggestions kept (per locale set) | $N$ | *Example:* 20 million | Log analysis above threshold |
| Average suggestion length | $\ell$ | *Example:* 20 characters | Log analysis |
| Distinct prefix nodes as share of total characters | $\sigma$ | *Example:* 0.3 | Trie build on a sample |

### 3.2 Request rate

$$
QPS = \frac{U \times q \times r}{86\,400} = \frac{10^{8} \times 5 \times 4}{86\,400} \approx 23\,000 \ \text{req/s}, \qquad \text{peak} \approx 69\,000 \ \text{req/s}
$$

Origin load after the edge cache:

$$
QPS_{origin} = (1 - h) \times 69\,000 \approx 27\,600 \ \text{req/s at peak}
$$

### 3.3 Index size

Prefix nodes:

$$
P = N \times \ell \times \sigma = 2 \times 10^{7} \times 20 \times 0.3 = 1.2 \times 10^{8} \ \text{nodes}
$$

With a top-10 list of 4-byte suggestion IDs (40 B) plus about 24 B of node
structure:

$$
M_{trie} \approx 1.2 \times 10^{8} \times 64 \ \text{B} \approx 7.7 \ \text{GB}
$$

plus suggestion strings and scores ($2 \times 10^{7} \times 32$ B $\approx 0.64$ GB),
about 8.3 GB per replica. Each suggest server holds a full replica, so no
cross-node calls are needed on the request path.

### 3.4 Pipeline volume

$$
L_{day} = U \times q = 5 \times 10^{8} \ \text{search events/day} \times 200 \ \text{B} \approx 100 \ \text{GB/day}
$$

### 3.5 Summary

| Quantity | Estimate | Design consequence |
|---|---|---|
| Requests | ~69 000/s peak, ~28 000/s at origin | Small fleet of in-memory servers behind edge cache |
| Index | ~8.3 GB per replica | Full replica per server; no sharding needed yet |
| Log volume | ~100 GB/day | Hourly batch aggregation is cheap |
| Latency | 20 ms server budget | No disk or network hop on the hot path |

## 4. API design

<!-- Guidance: Define the contract first: resources, methods, request and response shapes, errors, idempotency, pagination, rate limits and versioning. Use RFC 9457 problem details for errors. -->

### 4.1 Endpoints

| Method | Path | Purpose | Auth | Cacheable |
|---|---|---|---|---|
| GET | `/v1/suggest?q={prefix}&locale={loc}&n=10` | Suggestions for a prefix | None or session | Yes, for anonymous requests |
| POST | `/v1/suggest/feedback` | Report a suggestion | Session | No |
| POST | `/internal/v1/blocklist` | Add a term or pattern (policy team) | Admin role | No |

### 4.2 Request and response examples

The prefix is normalised (case-folded, whitespace collapsed) on the client and
the server so cache keys match:

```http
GET /v1/suggest?q=wint&locale=en-GB&n=8 HTTP/1.1
```

```http
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: public, max-age=300
Vary: Accept-Encoding

{"q": "wint", "indexVersion": "2026-03-14T09", "suggestions": [{"text": "winter coats", "kind": "query"}, {"text": "winter tyres", "kind": "query"}, {"text": "winter olympics schedule", "kind": "trending"}]}
```

### 4.3 Errors and limits

| Status | Problem type | When |
|---|---|---|
| 400 | `prefix-too-long` | Prefix over 100 characters |
| 429 | `rate-limited` | Client over 20 requests/s; `Retry-After` set |

Clients treat any error or a response slower than 300 ms as "no
suggestions"; typing is never blocked.

## 5. Data model

<!-- Guidance: Choose storage by access pattern, not by habit. Show entities, keys, partitioning and the queries each store must answer. -->

### 5.1 Entities

The pipeline turns raw query events into scored suggestions; an index build
packages them for serving.

```mermaid
erDiagram
  QUERY_EVENT {
    string event_id PK
    string normalized_query
    string locale
    string anon_user_hash
    datetime at
  }
  QUERY_STATS {
    string normalized_query PK
    string locale PK
    date day PK
    bigint count
    bigint distinct_users
  }
  SUGGESTION {
    int suggestion_id PK
    string text
    string locale
    float score
    string source
  }
  BLOCK_RULE {
    string rule_id PK
    string pattern
    string match_type
    string reason
    datetime added_at
  }
  INDEX_BUILD {
    string version PK
    datetime built_at
    int suggestion_count
    string checksum
  }
  QUERY_STATS ||--o{ SUGGESTION : "aggregates into"
  BLOCK_RULE ||--o{ SUGGESTION : "filters"
  INDEX_BUILD ||--|{ SUGGESTION : packages
```

### 5.2 Storage choices

| Data | Store | Key | Main queries | Why |
|---|---|---|---|---|
| Query events | Event stream, then data lake (partitioned by hour) | Time | Batch aggregation | Cheap, append-only |
| Query stats | Data warehouse table | Query, locale, day | Score computation | SQL-friendly batch |
| Index builds | Object storage, versioned files | `version` | Download by servers | Immutable artifacts, easy rollback |
| Trending counters | In-memory stream processor state | Query, locale, window | Top-k per window | Minutes-level freshness |
| Block rules | Relational database, replicated to servers | `rule_id` | All active rules | Audited, small |

## 6. High-level design

<!-- Guidance: One diagram that shows every component on the request paths and where state lives. Name components by responsibility. -->

The serving path is read-only and in memory; all heavy work happens in the
pipeline.

```mermaid
flowchart LR
  client([Search box]) --> edge[CDN edge cache]
  edge -->|miss| lb[Load balancer]
  lb --> sug[Suggest servers]
  sug --> idx[(In-memory index replica)]
  sug --> trend[(Trending top-k cache)]
  sug --> block[(Block rules)]
  client -->|search events| ingest[Event ingestion]
  ingest --> lake[(Data lake)]
  ingest --> stream[Stream processor]
  stream --> trend
  lake --> agg[Hourly aggregation and scoring]
  agg --> filt[Policy filter]
  filt --> build[Index builder]
  build --> store[(Versioned index files)]
  store --> sug
```

| Component | Responsibility | Scales by |
|---|---|---|
| Suggest servers | Look up prefix, merge trending, filter, return top N | Replicas (each holds full index) |
| Stream processor | Count queries per 5-minute window, detect spikes | Partitions by query hash |
| Aggregation and scoring | Compute decayed popularity per query and locale | Batch cluster |
| Policy filter | Apply block rules, privacy thresholds | Batch step |
| Index builder | Build trie with top-k per node, validate, publish | Single batch job per locale group |
| [Component] | [Responsibility] | [Scaling unit] |

## 7. Detailed design

<!-- Guidance: Go deep on the parts that are new, risky or contested. Show the sequence of calls and the failure behaviour of each step. -->

### 7.1 Prefix index options

| Structure | Lookup | Memory | Updates | Fit |
|---|---|---|---|---|
| Trie with top-k cached per node | O(prefix length) then read list | Largest | Rebuild or careful in-place | Chosen: fastest, simple serving |
| Finite state transducer (FST) | O(prefix length) plus traversal for top-k | Smallest (shares prefixes and suffixes) | Immutable, rebuild | Good when memory bound; top-k needs weighted traversal |
| Edge n-grams in a search engine | Inverted index query | Large (every prefix indexed) | Near real time | Good when suggestions need full-text features and filters |
| Sorted array + binary search | O(log N) then scan | Small | Rebuild | Simple baseline; top-k needs scan of range |

The trie stores, at each node, the IDs of the 10 highest-scoring suggestions
in its subtree, computed bottom-up during the build. A lookup walks the prefix
and returns that list without exploring the subtree.

### 7.2 Ranking

Base score for query $x$ in locale $\ell$ uses exponentially decayed daily
counts with half-life $h$ (*Example:* 7 days):

$$
S(x) = \sum_{d=0}^{D} c_{x,d} \cdot 2^{-d/h}
$$

At serve time, the trending layer adds a boost when the last window greatly
exceeds the expected rate:

$$
\text{boost}(x) = \max\left(0,\ \log_2 \frac{c_{x,\,5min} + 1}{\mu_{x,\,5min} + 1}\right)
$$

where $\mu$ is the average 5-minute count over the last 7 days. A query seen
16 times more than usual gets a boost of about 4 score units; the weight of the
boost against $S$ is tuned with online experiments. Final order also applies
diversity (no more than 3 suggestions sharing the same first two words).

### 7.3 Data pipeline

| Stage | Frequency | Work | Output |
|---|---|---|---|
| Ingest | Continuous | Normalise query, drop events from known bots, hash user ID with rotating salt | Events in lake and stream |
| Aggregate | Hourly | Count per query, locale, day; count distinct users | Query stats |
| Threshold | Hourly | Keep queries with at least 50 distinct users in 30 days | Candidate suggestions |
| Filter | Hourly | Apply block rules, PII detectors (emails, phone numbers, ID numbers) | Clean suggestions |
| Build | Hourly | Build trie per locale group, compute checksums, run golden-prefix tests | Index version |
| Publish | Hourly | Upload; servers download, load into memory, swap atomically | Serving index |

Servers keep the previous version in memory until the new one passes a
self-test, so a bad build never serves.

### 7.4 Suggest request (critical path) and caching

Short prefixes are the most requested and the least personal, so they are
cached at the edge; longer prefixes go to origin.

```mermaid
sequenceDiagram
  participant B as Browser
  participant E as CDN edge
  participant S as Suggest server
  participant I as Index (memory)
  participant T as Trending cache
  B->>B: debounce 100 ms, normalise prefix
  B->>E: GET /v1/suggest?q=wint&locale=en-GB
  alt edge hit (prefix length 1-3 or popular)
    E-->>B: cached suggestions
  else miss
    E->>S: forward
    S->>I: walk prefix "wint"
    I-->>S: top-10 IDs
    S->>T: trending for "wint"
    T-->>S: 0-2 trending queries
    S->>S: merge, apply live block rules, cut to n
    S-->>E: 200, max-age 300
    E-->>B: suggestions
  end
  B->>B: blend local recent searches, render
```

Clients also keep a small in-memory cache: if "win" returned 10 results and the
user types "wint", the client can filter locally while the request is in
flight.

### 7.5 Personalisation

Personal recent searches stay on the device (local storage, last 50 entries,
user-clearable) and are blended on the client by prefix match, which keeps
edge responses cacheable and avoids server-side profiles. Signed-in users may
opt in to sync history; synced history is encrypted at rest, deletable, and
never used to train global suggestions.

### 7.6 Abuse and safety filtering

- **Block rules**: exact terms, patterns and entity lists maintained by the
  policy team; applied in the pipeline and again at serve time so a new rule
  takes effect within the 10-minute rule-sync interval without a rebuild.
- **Manipulation**: coordinated query injection is limited by the
  distinct-user threshold, bot filtering and caps on the trending boost per
  source network.
- **Privacy**: the threshold and PII detectors prevent rare personal queries
  (names with addresses, account numbers) from becoming suggestions.

### 7.7 Consistency model

All servers converge on the same index version within one publish cycle;
during rollout two versions may serve for up to 10 minutes, which users cannot
notice. Block-rule removals are the only change with a hard deadline (FR-07)
and are pushed separately from index builds.

## 8. Scalability and performance

<!-- Guidance: Show how the design meets the numbers in section 3 and where it will break first. -->

| Concern | Approach | Limit before redesign |
|---|---|---|
| Request rate | Stateless replicas, edge cache | *Example:* ~5 000 req/s per server, so 6 servers for peak origin load plus 2 spare |
| Index memory | Full replica per server | When index exceeds ~50% of server memory, shard by locale group |
| Build time | Parallel per locale group | Hourly cadence needs builds under 20 min |
| Long-tail prefixes | Served from origin; edge only for short ones | [Limit] |

Latency budget, keystroke to rendered suggestions (target p95 100 ms):

| Step | Budget |
|---|---|
| Debounce | 0 ms after last pause (not counted) |
| Network to edge (round trip) | 30 ms |
| Edge to origin on miss (round trip) | 25 ms |
| Server processing (lookup, merge, filter) | 5 ms |
| Client blend and render | 10 ms |
| Headroom | 30 ms |

## 9. Reliability, security and operations

<!-- Guidance: Name the failure modes, the threats and the signals operators watch. Each mitigation should be testable. -->

### 9.1 Failure modes

| Failure | Impact | Detection | Mitigation |
|---|---|---|---|
| Bad index build | Wrong or empty suggestions | Golden-prefix tests, size and checksum checks | Build rejected; servers keep previous version |
| Pipeline delayed | Stale suggestions | Index age metric | Serve last good index; trending layer still fresh |
| Trending stream down | No trending boosts | Window lag metric | Serve base index only |
| Edge cache poisoning by personal data | Leak of one user's suggestions | Response audit | Only anonymous, non-personalised responses are cacheable (`private` otherwise) |
| Suggest servers down | No suggestions | Synthetic checks | Search box works without them; client timeout 300 ms |
| [Failure] | [Impact] | [Signal] | [Mitigation] |

### 9.2 Security, privacy and abuse

| Threat | Control |
|---|---|
| Offensive or defamatory suggestions | Block rules, reporting with 10-minute takedown, human review queue |
| Suggestion manipulation by bots | Distinct-user threshold, bot filtering, trending caps |
| Personal data in suggestions | Threshold of 50 users, PII detectors, hashed user IDs with rotating salt |
| Scraping of the suggestion corpus | Rate limits per IP; corpus is low sensitivity by design |
| Retention of query logs | *Example:* Raw events 30 days, aggregates 13 months |
| [Threat] | [Control] |

### 9.3 Observability

| Signal | Metric or log | Alert threshold |
|---|---|---|
| Server latency | p99 | Above 20 ms for 10 min |
| Perceived latency | Client RUM p95 | Above 100 ms for 30 min |
| Index age | Now minus build time | Above 2 h |
| Suggestion acceptance | Share of searches that used a suggestion | Drop of 10% vs. baseline |
| Safety | Reports per million impressions | Spike above 3x baseline |

### 9.4 Cost estimate

| Item | Unit cost | Quantity | Monthly cost |
|---|---|---|---|
| Suggest servers (32 GB RAM) | [$/node-month] | *Example:* 12 per region | [$] |
| CDN requests | [$/million] | *Example:* ~1.2 billion edge hits/day | [$] |
| Pipeline compute | [$/hour] | 24 builds/day | [$] |
| Data lake storage | [$/TB-month] | *Example:* 3 TB (30 days raw) | [$] |
| **Total** | | | **[$]** |

## 10. Trade-offs and alternatives

<!-- Guidance: For each major decision list the options, what each costs and why you chose one. Reviewers will propose the alternatives anyway; answer them here. -->

| Decision | Options | Chosen | Why | What we give up |
|---|---|---|---|---|
| Index structure | Trie top-k; FST; edge n-grams in search engine | Trie top-k | Constant-time top-k, simplest hot path | More memory than FST |
| Freshness | Real-time index updates; hourly rebuild + trending layer | Hourly + trending | Immutable builds are safe and testable; trending covers news | Two layers to merge |
| Personalisation | Server profiles; device-local history | Device-local | Privacy, edge cacheability | No cross-device history without opt-in |
| Caching | No edge cache; cache all; cache short prefixes | Short prefixes | Most traffic at lowest cost | Long prefixes always hit origin |
| Typo tolerance | None; fuzzy trie traversal; separate spell index | Deferred (Could) | Complexity versus small gain at launch | Fewer results for misspellings |
| [Decision] | [Options] | [Chosen] | [Why] | [Cost] |

## 11. Delivery plan and risks

<!-- Guidance: How the design reaches production safely, and what could stop it. -->

### 11.1 Milestones

| Milestone | Scope | Exit criterion | Target date |
|---|---|---|---|
| M1 | Pipeline and daily index, one locale | Golden-prefix tests pass; p99 under 20 ms | YYYY-MM-DD |
| M2 | Hourly builds, edge cache, all locales | Acceptance rate up vs. old system in A/B | YYYY-MM-DD |
| M3 | Trending layer and reporting flow | Trending visible within 15 min; takedown under 10 min | YYYY-MM-DD |
| M4 | Device-local personal history | Privacy review signed | YYYY-MM-DD |

### 11.2 Rollout and rollback

[*Example:* A/B test against the old endpoint for 2 weeks per locale.
Rollback flips the client config back to the old endpoint; index rollback
pins servers to a previous version.]

### 11.3 Risks

| ID | Risk | Likelihood | Impact | Mitigation | Owner |
|---|---|---|---|---|---|
| R-01 | *Example:* Harmful suggestion goes viral | Low | High | Dual filtering, fast takedown, on-call policy contact | [@name] |
| R-02 | *Example:* Index outgrows server memory | Medium | Medium | Shard by locale group; FST evaluation ready | [@name] |
| R-03 | *Example:* Trending boost amplifies manipulation | Medium | Medium | Caps per source network, human review of top trending | [@name] |
| [R-nn] | [Risk] | [L / M / H] | [L / M / H] | [Mitigation] | [@name] |

## 12. Appendices

<!-- Guidance: Supporting detail, glossary and open questions. -->

### 12.1 Open questions

| ID | Question | Owner | Due |
|---|---|---|---|
| OQ-01 | *Example:* Do we suggest product entities as well as queries? | [@name] | YYYY-MM-DD |
| OQ-02 | *Example:* Which locales share an index? | [@name] | YYYY-MM-DD |
| [OQ-nn] | [Question] | [@name] | YYYY-MM-DD |

### 12.2 Glossary

| Term | Meaning |
|---|---|
| Prefix | Characters typed so far |
| Trie | Tree keyed by characters where each path is a prefix |
| FST | Finite state transducer: compact automaton mapping strings to values |
| Edge n-gram | Indexing every leading substring of a term |
| Debounce | Waiting for a short pause in typing before sending a request |
| [Term] | [Meaning] |

### 12.3 References

| Reference | Use |
|---|---|
| RFC 9111 HTTP Caching | Edge caching rules in 7.4 |
| RFC 9110 HTTP Semantics | API and `Retry-After` |
| [Search engine documentation on completion suggesters] | Alternative in 7.1 |
| [Internal content policy for suggestions] | Filtering in 7.6 |

## Standard and licence note

Based on common industry practice for search autocomplete design and on the
HTTP specifications cited in 12.3. This is a reference design to adapt, with
illustrative numbers. Original text written for this collection. Template
licence: MIT.
