How do you handle backpressure when a UI event queue grows faster than you can process it?

Hey everyone, I’m wiring up a little client-side queue for analytics events in a React app, and I’m trying to keep the UI smooth when users spam actions. Right now I just push into an array and drain it in chunks, but if the network is slow the queue grows, memory creeps up, and sometimes events arrive too late to be useful.

const queue = [];
let inflight = 0;
const MAX_INFLIGHT = 3;

export function track(evt) {
  queue.push({ evt, t: performance.now() });
  pump();
}

async function pump() {
  while (inflight < MAX_INFLIGHT && queue.length) {
    inflight++;
    const batch = queue.splice(0, 25);
    sendBatch(batch).finally(() => {
      inflight--;
      pump();
    });
  }
}

What’s a sane algorithm/data-structure approach here (drop-oldest, coalesce by key, ring buffer, priority queue, etc.) so I don’t blow up memory but also don’t lose the “important” events?

1 Like

splice(0, 25) is the part i’d fix first — it reindexes the whole array every drain, so the queue itself starts stealing time from the UI.

I’d use a bounded queue with a head index or a ring buffer, drop the oldest items when it’s full, and coalesce noisy stuff by key so you don’t keep 40 copies of the same click. For the events you really care about, keep a tiny high-priority lane that never gets merged with the junk.

That’s usually enough for analytics. Once the network is slow, trying to preserve every single event just turns into memory creep and stale data anyway.