Design a client-side event batching system for a high-traffic app

This tests your grasp of frontend performance and data reliability. Outline a batching strategy (timer/size), then explain using visibilitychange with navigator.sendBeacon() to prevent data loss on unload. A red flag is suggesting synchronous XHR.
What's really being asked
This question evaluates your practical knowledge of client-side performance engineering. The interviewer is looking for your ability to design a system that balances network efficiency with data integrity. They want to see if you understand the lifecycle of a web page, the limitations of standard network requests during unload, and modern browser APIs designed to solve these exact problems. It's not just about knowing sendBeacon; it's about knowing why and when to use it versus other techniques.
The full answer
A strong answer outlines a four-part strategy. First, describe the core batching mechanism: events are pushed into an in-memory queue, like a JavaScript array. Second, explain the dispatch triggers: the queue is flushed and sent to the server when either a timer expires (e.g., every 15 seconds) or the queue reaches a certain size (e.g., 50 events). Third, address the critical data loss problem on page unload by listening for the visibilitychange or pagehide events. These events signal the user is leaving. Fourth, for this final unload dispatch, specify using navigator.sendBeacon(). It is ideal because it's asynchronous, non-blocking, and designed for this exact use case, ensuring the request is sent even after the page has unloaded. Mention fetch() with the keepalive: true flag as a more flexible alternative that also works on unload.
The mistakes people make
A major red flag is suggesting outdated or harmful techniques for handling unload. This includes using a synchronous XMLHttpRequest, which is deprecated and freezes the UI, creating a terrible user experience. Another common mistake is creating a no-op loop or setting an image src to delay the unload; these are unreliable hacks. Simply ignoring the unload problem and accepting data loss is also a poor answer for a senior candidate. Finally, suggesting sendBeacon for all requests during the session is suboptimal; fetch is better for regular, in-session batch sends where you might care about the response.
What usually comes next
Expect questions about the limits of sendBeacon. For example, "What is the payload size limit for sendBeacon?" (It's 64KB). Or, "What if you need to send more data than that on unload?" (The answer is fetch({ keepalive: true })). They might also ask about error handling: "How do you handle a false return from sendBeacon()?" (It means the browser couldn't queue the request, likely because the data was too large). Another follow-up could be about server-side implications, like handling out-of-order events.
A concrete example
"We'll collect user interaction events in an array. We will use setInterval to send the batch every 10 seconds. If the array is empty, we do nothing. We'll also add an event listener for visibilitychange. If document.visibilityState becomes hidden, we immediately trigger a final send of any remaining events in the queue using navigator.sendBeacon(url, JSON.stringify(queue)). This ensures we capture the last few events before the user navigates away, without blocking their next action."
Interview question
When designing a client-side event batching system, why is navigator.sendBeacon() preferred for dispatching final events during page unload?
- a.It is specifically designed to send data asynchronously and non-blocking, ensuring the request is sent even after the page has unloaded without freezing the UI.Correct
- b.It automatically handles network retries and guarantees event ordering on the server, simplifying backend implementation.
- c.It provides a reliable callback mechanism to confirm server receipt of data before the page closes.
- d.It allows for sending arbitrarily large data payloads, exceeding typical XMLHttpRequest limits, which is crucial for large event batches.
Why? this is the answer
navigator.sendBeacon() is ideal for unload because it's asynchronous and non-blocking, ensuring data is sent without freezing the UI or being canceled by page unload. Option C is incorrect because sendBeacon is a fire-and-forget mechanism and does not provide a callback for server receipt.
Just read this? Test yourself on what you have been reading.
Read the original → developer.mozilla.org
- #frontend
- #performance
- #browser-apis
- #analytics
- #system-design
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.
We are hiring for this. Open roles that interview on frontend — each one lists the topics its interview covers.
See open roles