Launch offer: the first 1,000 users get Settl free for a year*Claim your spot
settlbuilding in public

Debounced Search Requests Pack

Debounce and throttle both reduce event calls, but they solve different problems.

Use debounce when only the final value matters. A search box usually belongs here: every keystroke resets a short timer, and one request runs after typing stops. Use throttle when intermediate updates matter, such as pointer movement or scroll progress.

A safe search sequence

For every query change:

  1. Clear the pending debounce timer.
  2. Cancel the previous request if the client and transport support it.
  3. Start a new timer for a measured delay, often around a few hundred milliseconds.
  4. When it fires, assign the request a monotonically increasing sequence number.
  5. Apply the response only if its query and sequence still match the latest state.

Cancellation saves work, but the sequence guard protects correctness. A server may finish an already-running request even after the client aborts it. Without the guard, results for sho can arrive after results for shoes and replace the right screen with the wrong list.

Do not debounce the input value itself. The text field should update immediately. Debounce only the expensive search action. Show a loading state after the request begins, preserve keyboard focus and selection, and announce result changes for screen readers.

Clear timers and abort requests when the component unmounts. Otherwise a stale callback can update a new screen, throw a warning, or leak work.

Choose the delay with evidence

One second feels broken for ordinary typing because each new key restarts the wait. A tiny delay may still fire several requests during a pause. Measure typing and endpoint latency for your users, then test a small range. Keep immediate behaviour for explicit submit, saved searches, and keyboard selection.

Verification checklist

  1. Type five characters under fake timers. Exactly one debounced request fires.
  2. Pause between characters and confirm the documented request count.
  3. Return the oldest request last. Its response is ignored.
  4. Clear the field while a request is running. Old results do not reappear.
  5. Unmount the component and prove timers and requests are cleaned up.
  6. Use only the keyboard to type, wait, select, and submit.
  7. Check loading and result-count announcements with a screen reader.

The runnable starter returns the debounce/throttle decision, timer lifecycle, cancellation plan, stale-response guard, loading-state contract, and fake-timer tests. Dry-run calls no search service.

Download the runnable pack

Comment DEBOUNCE for the pack. One waits for silence; the other keeps a steady beat.

Get the next one in your inbox