Romaji to Kana Converter: React & Next.js — Chapter 5, Exercise 3 ===================================================================== TASK Explain, in your own words, why the client-side box needs no debounce and no request-id guard at all, while the server-comparison box genuinely needs both -- tracing each requirement back to a specific real finding from Chapter 4. SOLUTION Both real requirements this chapter added to the server box trace back to the exact same root cause: the server box makes a real network request on every keystroke, and the client-side box doesn't make any network request at all. No debounce needed on the client-side box. Chapter 4 measured a direct convert() call at well under a microsecond per call -- so far below the real interval between two human keystrokes (routinely 50-100 milliseconds even for a fast typist) that there's no meaningful cost to batch away. Debouncing exists specifically to reduce how often an expensive operation runs; convert() is cheap enough that "how often it runs" was never a real problem in the first place. The server box, by contrast, is paying Chapter 4's own real measured ~14ms-per-request cost on every keystroke if nothing holds it back -- genuinely expensive enough, multiplied across a fast typist's own real keystroke rate, to justify batching requests behind a short delay. No request-id guard needed on the client-side box. A guard exists to solve one specific problem: two overlapping asynchronous operations whose real-world completion order doesn't match the order they were started in, so a stale result can arrive after a newer one and silently overwrite it. convert() is a plain, synchronous function call -- it returns its result immediately, in the same tick it was called, with no way for a second call to "still be in flight" when a third one starts. There's only ever one convert() result in existence at any moment, so there's no way for an older one to arrive out of order, because nothing is ever waiting to arrive at all. The server box's own fetch() calls are genuinely asynchronous network requests with real, variable latency -- exactly the situation Chapter 4's own race condition demonstration was built to reproduce -- so a guard is what actually protects it. Put together: both of this chapter's own real design choices for the server box are direct, traceable consequences of the same underlying fact Chapter 4 established with real numbers -- a network call is slow and asynchronous where a local function call is fast and synchronous -- not two unrelated rules that happen to apply to one box and not the other. WHY THIS WORKS AS AN ANSWER ---------------------------- It identifies the single shared root cause (network call vs. local function call) behind both real design decisions, rather than listing them as two separate facts, and ties each one back to the specific Chapter 4 finding (the sub-microsecond direct-call cost, and the real reproduced out-of-order race condition) that actually justifies it.