Skip to main content
Each step() call, and each pageview when trackPageviews is on, pushes an event onto an in-memory queue. The queue drains in batches, so a busy page makes a handful of requests instead of one per event. Every request goes through fetch; navigator.sendBeacon is never used.

Automatic flush triggers

1

Timer interval

A timer fires every flushInterval milliseconds (default: 5000 ms) and sends one batch. The timer only runs in the browser.
2

Batch size threshold

If the queue reaches maxBatchSize events before the timer fires, the SDK flushes immediately. The default is 50 events per batch; the hard maximum per request is 100 events. There is no payload byte limit, only the event count cap.
3

Page hide

On visibilitychange to hidden and on pagehide, the SDK drains the entire queue with parallel fetch requests using keepalive: true, so the browser completes them even as the page unloads.
destroy() also sends one last batch after it removes the timer and listeners.

The internal queue

The queue holds at most 1000 events. When a new step() call overflows it, the oldest events are dropped to make room. When a failed batch is re-queued at the front and overflows it, the newest events are dropped instead. With a flush every few seconds the queue stays far below this limit. If your users go offline for long stretches, lower flushInterval and maxBatchSize so the backlog drains in smaller, more frequent batches once they reconnect.

Retry behavior

There is no backoff and no retry cap; a failing batch is retried on every flush trigger until it succeeds, is dropped by a 4xx, or is pushed out of the queue.

Manual flush methods

flush()

Sends at most one batch (up to maxBatchSize events) per call using fetch. Returns a Promise that resolves once the request settles; it never rejects, and failed batches are re-queued.
You rarely need flush(). The one real use is a send attempt that has to settle before something else happens, like a redirect to an external checkout page.

sendBeacon()

Drains the entire queue in parallel fetch requests with keepalive: true, one per batch of up to 100 events. The name is historical: it never calls navigator.sendBeacon, because keepalive fetch can carry the API key header and still outlive the page. Returns a Promise that resolves when all requests settle; failures are re-queued. If fetch is unavailable, events are retained.
visibilitychange and pagehide are hooked for you. Call sendBeacon() yourself only if a custom unload flow bypasses those events.

Summary