tezvyn:

Design client-side event batching and prevent unload data loss

Curated by the Tezvyn teamSource: developer.mozilla.orgadvanced
Design client-side event batching and prevent unload data loss

It tests balancing network efficiency and data reliability in browser analytics. Strong answers cover in-memory batching with size or time triggers, sendBeacon or fetch keepalive on visibilitychange, and a retry queue.

WHAT THIS TESTS: This question evaluates your ability to design a browser-based telemetry pipeline that optimizes for both network efficiency and data durability. Interviewers want to see that you understand the tension between batching events to reduce request overhead and the risk of losing in-memory data when the user navigates away or closes the tab. They are also checking for concrete knowledge of browser lifecycle events and modern APIs that solve the unload problem without degrading user experience.

A GOOD ANSWER COVERS: First, an in-memory batching strategy using a ring buffer or queue with two flush triggers: a maximum batch size, such as 100 events or 50 KB, and a time-based flush, such as every 5 seconds, whichever comes first. Second, a dual-path transport where standard fetch is used during normal operation for its flexibility and response handling, while page termination events trigger a fallback to navigator.sendBeacon or fetch with keepalive set to true. Third, persistence and retry logic using IndexedDB or localStorage to store failed or pending batches so that data survives page reloads and offline periods. Fourth, explicit handling of the unload lifecycle by listening for visibilitychange rather than relying solely on beforeunload, because visibilitychange fires more reliably on mobile and modern browsers.

COMMON WRONG ANSWERS: Relying on synchronous XMLHttpRequest inside a beforeunload handler is a major red flag because it blocks the main thread and harms perceived navigation speed. Another mistake is assuming fetch alone is sufficient for unload scenarios without the keepalive flag, since standard fetch requests may be cancelled by the browser during page teardown. Candidates also err by ignoring payload size limits, specifically the 64 KiB cap on sendBeacon, which makes fetch keepalive necessary for larger final batches. Finally, proposing only in-memory storage with no disk-backed retry queue signals a lack of resilience planning.

LIKELY FOLLOW-UPS: The interviewer may ask how you would handle backpressure if the server returns 500 errors or the client goes offline. They might also probe the tradeoffs between localStorage and IndexedDB for the retry queue, or ask how to guarantee ordering across batched and retried events. Another common angle is privacy and consent: how would you respect a do-not-track signal or GDPR deletion request within this pipeline.

ONE CONCRETE EXAMPLE: Suppose a user clicks a checkout button after generating 24 analytics events. Your batcher has accumulated 45 events totaling 30 KB. On the click, the page begins navigating away. The visibilitychange listener fires, so the batcher moves the 30 KB payload from memory to sendBeacon because it is under the 64 KiB limit. If the payload were 80 KB, the system would instead use fetch keepalive to send the larger batch. Meanwhile, if the network is offline, the batch is written to an IndexedDB outbox and flushed on the next page load using a background sync or a simple retry loop.

Source: developer.mozilla.org

Read the original → developer.mozilla.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.