# How the Buffered Event Queue Works with 10k Capacity in Ego-Lite

> Discover how Ego-Lite's 10k capacity buffered event queue discards old events when full. Learn about its efficient memory management for CDP events.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: internals
- Published: 2026-07-28

---

**Ego-Lite caps its CDP event buffer at 10,000 entries, automatically discarding the oldest events via array splicing when the limit is exceeded.**

The citrolabs/ego-lite browser runtime maintains a fixed-size **buffered event queue** to capture Chrome DevTools Protocol (CDP) events without unbounded memory growth. This circular buffer implementation ensures long-running automation sessions remain stable while preserving recent diagnostic data for retrieval.

## Core Implementation Details

### The 10,000 Event Capacity Limit

In [`package/ego-browser/src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts), the runtime defines a hard limit at lines 6-9:

```typescript
const MAX_BUFFERED_EVENTS = 10000;

```

This constant establishes the absolute upper bound for stored CDP events, creating a fixed memory footprint regardless of session duration.

### Event Capture and Storage

The queue stores events in a simple array initialized at line 20:

```typescript
const events = [];

```

When the embedded browser emits a CDP message, the `handleMessage` function processes it. Events not explicitly consumed by registered `subscribeBrowserEvent` listeners are pushed onto this array at lines 86-88:

```typescript
events.push(event);

```

### Automatic Truncation Mechanism

To enforce the **10k capacity**, the runtime implements immediate truncation. After each push operation at lines 88-90, the code executes:

```typescript
if (events.length > MAX_BUFFERED_EVENTS) {
  events.splice(0, events.length - MAX_BUFFERED_EVENTS);
}

```

This removes the oldest entries from the beginning of the array, maintaining a rolling window of exactly the most recent 10,000 events.

## Retrieving Buffered Events

Consumers access the queue through `drainBrowserEvents()` (lines 64-67), which returns all accumulated events and clears the buffer:

```typescript
drainBrowserEvents(): CDPEvent[] {
  return events.splice(0, events.length);
}

```

This method is exposed via the helper API and invoked by the CLI `drain` command defined in [`package/ego-browser/src/format.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/format.ts).

## Practical Code Examples

### Subscribing to Specific Events While Buffering Others

```javascript
// Subscribe to network requests specifically
await subscribeBrowserEvent(
  "Network.requestWillBeSent",
  undefined,
  (ev) => console.log("Request:", ev.params.request.url)
);

// Later, retrieve any other buffered events for debugging
const allBuffered = await drainBrowserEvents();
console.log(`Buffered ${allBuffered.length} CDP events`);

```

### Waiting for Events then Draining Remaining Buffer

```javascript
// Wait for page load with 5 second timeout
const navigation = waitForBrowserEvent(
  (ev) => ev.method === "Page.loadEventFired",
  5000
);
await navigation;

// Access events that accumulated during the wait
const leftovers = await drainBrowserEvents();
console.log(leftovers);

```

### Demonstrating the 10k Capacity Limit

This test-only simulation shows the truncation behavior:

```javascript
const MAX_BUFFERED_EVENTS = 10000;
const events = [];

for (let i = 0; i < 12_000; i++) {
  events.push({ method: "Dummy.event", params: { index: i } });
  if (events.length > MAX_BUFFERED_EVENTS) {
    events.splice(0, events.length - MAX_BUFFERED_EVENTS);
  }
}

console.log(events.length);        // → 10000
console.log(events[0].params.index); // → 2000 (oldest preserved entry)

```

## Summary

- The **buffered event queue** in citrolabs/ego-lite hard-caps CDP event storage at **10,000 entries** via `MAX_BUFFERED_EVENTS` in [`package/ego-browser/src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts).
- When capacity is exceeded, the runtime automatically removes the oldest events using `Array.splice()` to maintain fixed memory usage.
- Unhandled events are pushed to the buffer inside `handleMessage` (lines 86-88) and immediately truncated if necessary (lines 88-90).
- Retrieve accumulated events by calling `drainBrowserEvents()`, which returns the array and clears the queue.
- This implementation provides an "IOk" (input-output-known) memory footprint suitable for long-running browser automation without leaks.

## Frequently Asked Questions

### What happens when the buffered event queue exceeds 10,000 events?

When the queue surpasses the limit defined by `MAX_BUFFERED_EVENTS`, the runtime automatically truncates the oldest entries. Specifically, after pushing a new event, `handleMessage` executes `events.splice(0, events.length - MAX_BUFFERED_EVENTS)`, removing excess events from the beginning of the array while preserving exactly the most recent 10,000 entries.

### How do I access events stored in the buffer?

Call `drainBrowserEvents()` to retrieve all currently buffered CDP events and clear the queue. According to lines 64-67 in [`package/ego-browser/src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts), this function returns the entire event array and resets the internal buffer to empty using `events.splice(0, events.length)`, making it ideal for diagnostic logging or test verification.

### Where is the buffered event queue implemented in the source code?

The core implementation resides in [`package/ego-browser/src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts). Key components include the `MAX_BUFFERED_EVENTS` constant (lines 6-9), the `events` array storage (line 20), the `handleMessage` ingestion logic (lines 86-90), and the `drainBrowserEvents` retrieval method (lines 64-67). The CLI interface is defined in [`package/ego-browser/src/format.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/format.ts).

### Do subscribed events get added to the buffer?

No. Events consumed by `subscribeBrowserEvent` callbacks are delivered directly to your handler and are not added to the buffer. Only events that lack registered subscribers (excluding certain internal events like `Page.screencastFrame`) are pushed onto the `events` array for later retrieval via `drainBrowserEvents()`.