Typing gets much slower after 3+ characters
React incident
Search box typing lag under product-card load
Typing gets laggy after the third character because every keypress does too much work and also triggers a request.
Failure signals
The clues you start with
Most time is spent filtering and highlighting before the screen updates
Every keypress also sends a network request
Overview
What failed in production?
Start by making the bug legible: what the user saw, why it mattered, and what the product was doing underneath.
Symptom
Search feels fine at first, but once there are more matching items, each keypress feels about 200ms late.
User impact
Users think the input is missing characters and give up before finishing the search.
Environment
React 18 catalog page with about 2,400 product cards. The app also asks the server for suggestions on every change.
Evidence pack
What you can inspect before answering
Real-user timing
For slower real-world sessions, input delay jumps from about 40ms to a little over 200ms after the third character.
Profiler result
Most of the time is spent filtering items and building highlights before the screen updates.
Current handler
const onChange = (value: string) => {
setQuery(value);
setResults(expensiveFilter(allItems, value));
fetchSuggestions(value);
};Stage 1: likely root cause
What is most likely causing the lag?
Pick the cause that explains both the heavy JavaScript work and the sticky typing.
Correct. Too much synchronous work happens before the input can feel responsive.
Network can slow the results, but it does not explain the heavy JavaScript work shown in the profiler.
CSS can contribute, but the profiler points to JavaScript work before the screen updates, not hover styling.
There is no signal of duplicated handlers. The evidence points to heavy work, not repeated events.
Stage 2: debug priority order
What would you check first? Put the best three at the top.
First prove whether typing is blocked by local work, network delay, or both.
- #1Profile a real typing session in React DevTools or the browser Performance panel.See where the time goes before changing the architecture.
- #2Mock the network and measure only the local filter and highlight work.Separate frontend work from request delay.
- #3Throttle CPU and network separately to see which one hurts more.Find out whether the main problem is local work or request delay.
- #4Rewrite the suggestions endpoint before measuring the UI.Big change, weak first step.
- #5Add a debounce immediately and skip profiling.Common fix, but weak if you have not measured first.
Only the top 3 positions are scored.
Expected: Profile a real typing session in React DevTools or the browser Performance panel.
Expected: Mock the network and measure only the local filter and highlight work.
Expected: Throttle CPU and network separately to see which one hurts more.
Stage 3: best fix set
Which fixes should be in the first real patch?
Pick the changes that remove the bottleneck instead of just masking it.
This does not address input lag and can hide the real performance problem.
Correct. This cuts avoidable request churn and reduces work on the input path.
That can change dev noise, but it does not solve the production bottleneck.
Correct. The main win is removing blocking work from the typing path.
Correct. Rendering fewer cards lowers total update cost once the query changes.
Stage 4: regression guard
What is the best way to catch this kind of regression again?
Pick the signal that would warn you about sticky typing early.
API timing matters, but it misses the blocking render work shown in the incident.
Manual checks help, but they are too weak as the main guardrail.
Correct. This watches the actual user-facing failure mode instead of only backend timing.
That throws away product behavior instead of building a durable performance guardrail.
You started fixing before isolating the bottleneck
The lag was real, but you still needed to separate local work from request delay.
Good instincts, but the priorities were not fully clear
You found useful fixes, but the debug order or guardrail missed the main user-facing signal.
You isolated the lag clearly
You found the blocking work, chose layered fixes, and added a measurable guardrail.
Ideal runbook
How a strong answer should flow
- 1Profile the typing interaction before changing architecture.
- 2Separate local render cost from request delay.
- 3Reduce typing-path work first, then cut list rendering and request churn.
- 4Track the delay users actually feel after rollout.
Reflection
Reflection note
If this only happened on low-end phones, what would you measure first?
What this incident tests
Performance debugging gets easier when you first ask: is the delay coming from local work, network delay, or both?
Strong answer signals
- You measure before optimizing.
- You separate slow JavaScript work from slow network.
- You pick a metric that matches what the user actually feels.