Skip to content
tezvyn:

Design a Client-Side Event Batching System

Source: developer.mozilla.orgHardHow cards are made

Design a Client-Side Event Batching System

Tests your grasp of client-side performance, network optimization, and data loss edge cases. A great answer batches events in memory, sends them with fetch(), and uses navigator.sendBeacon() on pagehide to reliably send the final batch.

What's really being asked

This question evaluates your practical knowledge of front-end performance optimization and data reliability. The interviewer wants to see if you can design a system that reduces network chatter for a high-traffic app while also handling the critical edge case of data loss when a user navigates away. It's a test of your understanding of the browser lifecycle and modern APIs designed to solve these specific problems.

The full answer

A strong answer hits four points in order. First, the core batching mechanism: describe an in-memory data structure, like an array, to act as a queue for events. Second, the periodic sending logic: explain using setInterval to trigger a function every 10-15 seconds. This function uses the fetch() API to POST the batched data to an analytics endpoint and clears the queue on a successful response. Third, and most critically, handling unload: attach an event listener to the pagehide or visibilitychange events. Inside this handler, use navigator.sendBeacon(). This API is designed for this use case, reliably queueing a POST request to be sent by the browser without blocking the unload process. Fourth, trade-offs: mention the sendBeacon payload size limit (typically 64KB) and its fire-and-forget nature.

The mistakes people make

A major red flag is suggesting synchronous XMLHttpRequest in a beforeunload event handler. This is a deprecated practice that blocks the main thread and provides a terrible user experience. Another common mistake is forgetting the unload case entirely; simply batching with setInterval is an incomplete solution as the last batch of data will be lost. Sending every event individually also misses the entire point of the question. Finally, relying on unload or beforeunload events is less reliable than pagehide or visibilitychange for this task.

What usually comes next

"What if the final batch of data exceeds the 64KB limit of sendBeacon?" (Answer: Mention fetch({ keepalive: true }) as a modern alternative, but acknowledge trade-offs). "How would you make this system resilient to network failures during periodic sends?" (Answer: Implement a retry mechanism with exponential backoff for the fetch calls, but not for sendBeacon. You could also persist the queue to localStorage to survive page reloads, but be mindful of its limits).

A concrete example

A user clicks 5 buttons in 8 seconds. Instead of 5 POST requests, our system adds 5 event objects to an array. If our interval is 10 seconds, at the 10-second mark, a single fetch call sends a JSON payload with all 5 events. If the user then closes the tab at the 12-second mark after clicking two more buttons, the pagehide event fires. The handler immediately calls navigator.sendBeacon('/analytics', JSON.stringify([event6, event7])), ensuring the last two events are sent without delaying the tab closing.

Interview question

To prevent data loss in a client-side event batching system when a user closes the tab, which approach best balances reliability and user experience?

  • a.Decrease the `setInterval` duration for batch sends to 1 second to minimize the window for data loss.
  • b.Use `navigator.sendBeacon()` within a `pagehide` event listener to send the final batch asynchronously without blocking the page unload.Correct
  • c.Trigger a standard `fetch()` POST request in an `unload` event listener to send the remaining events.
  • d.Use a synchronous `XMLHttpRequest` inside a `beforeunload` event handler to block the page until the request completes.
Why?

`navigator.sendBeacon()` is designed for this exact use case, reliably sending data without blocking the unload process. A standard `fetch()` is not guaranteed to complete, and synchronous XHR is a deprecated practice that harms user experience.

Just read this? Test yourself on what you have been reading.

Read the original → developer.mozilla.org

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.

See open roles