# Session TTL and Caching Strategy in ego-lite browser-runtime: Complete Guide

> Learn ego-lite browser-runtime's session TTL and caching strategy. Discover how it reuses sessions, re-attaches expired ones, and buffers CDP events for optimal performance.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: deep-dive
- Published: 2026-08-25

---

**The session TTL in ego-lite's browser-runtime is hard-coded to 2 seconds, with a simple caching strategy that reuses valid sessions, lazily re-attaches expired ones, and buffers up to 10,000 CDP events.**

The `browser-runtime` module in [citrolabs/ego-lite](https://github.com/citrolabs/ego-lite) manages Chrome DevTools Protocol (CDP) connections for browser automation. Understanding its session TTL and caching strategy is essential for writing reliable, performant automation scripts that leverage session reuse without hitting stale connection issues.

---

## What Is the Session TTL?

The **session time-to-live (TTL)** is defined as a constant in [`package/ego-browser/src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts):

```ts
const SESSION_TTL_MS = 2000;  // 2 seconds

```

```ts
const MAX_BUFFERED_EVENTS = 10000;

```

This 2-second window determines how long the runtime will reuse an existing CDP session before forcing a fresh one.

---

## How Session Caching Works

### Cache Validation Logic

When a CDP request requires a session, the runtime checks the cache validity at lines 8-10 of [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts):

```ts
if (state.sessionId && Date.now() - state.sessionAt < SESSION_TTL_MS) {
  return state.sessionId;               // reuse cached session
}

```

The session state is managed in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts) and tracked through three key properties:

- **`sessionId`** – the active CDP session identifier
- **`sessionAt`** – timestamp of last successful session acquisition
- **`sessionInflight`** – promise preventing concurrent session creation

### Cache Invalidation

When a session becomes invalid (target closed, connection lost), the runtime clears all related state. The `invalidateSession()` function at lines 46-54:

```ts
function invalidateSession() {
  if (state.sessionId) {
    pageEnabledSessions.delete(state.sessionId);
    pendingDialogs.delete(state.sessionId);
  }
  state.sessionId = null;
  state.sessionTargetId = null;
  state.sessionAt = 0;
}

```

This ensures stale sessions don't cause silent failures on subsequent calls.

---

## CDP Event Buffering Strategy

Beyond session caching, the runtime implements **event buffering** to prevent memory exhaustion. Incoming CDP events accumulate in an internal `events` array, capped at `MAX_BUFFERED_EVENTS` (10,000 entries).

When the buffer exceeds this limit, oldest events are purged (lines 86-90):

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

```

This provides recent event history without unbounded growth.

---

## Practical Code Examples

### Reuse Cached Sessions Explicitly

```ts
import { ensureSession, browserCdp } from 'ego-browser';

// Returns cached session ID if still valid (≤2s), or creates new one
const sessionId = await ensureSession();
await browserCdp('Runtime.evaluate', { expression: 'document.title' }, sessionId);

```

### Automatic Session Handling

Most high-level helpers handle this transparently:

```ts
import { js } from 'ego-browser';

// Runtime automatically attaches fresh session if cache expired
const title = await js('document.title');
console.log('Page title:', title);

```

### Force Session Refresh

```ts
import { invalidateSession } from 'ego-browser';

// Clear cache to guarantee fresh session on next call
invalidateSession();
await browserCdp('Page.reload');   // ensures new session

```

### Access Buffered Events

```ts
import { drainBrowserEvents } from 'ego-browser';

// Retrieve accumulated events (up to 10,000 most recent)
const events = drainBrowserEvents();
console.log('Buffered events:', events.length);

```

---

## Key Implementation Files

| File | Purpose |
|------|---------|
| [`package/ego-browser/src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts) | Core transport, TTL constants, caching logic, event buffering |
| [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts) | Global mutable state (`sessionId`, `sessionAt`, `sessionInflight`) |
| [`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts) | High-level helpers using runtime session logic |
| [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) | Exposed API for agent scripts |

---

## Summary

- **Session TTL is fixed at 2 seconds** (`SESSION_TTL_MS = 2000`) in [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts)
- **Cache hit** reuses existing session; **cache miss** triggers `ensureSession()` for lazy re-attachment
- **Invalidation** occurs explicitly on connection loss or manually via `invalidateSession()`
- **Event buffer** holds up to 10,000 CDP events with automatic pruning of oldest entries
- All state centralized in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts), operations in [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts)

---

## Frequently Asked Questions

### Why is the session TTL only 2 seconds?

The 2-second window balances connection reuse against freshness. Browser automation targets frequently change state (page navigations, frame detachment). A short TTL ensures sessions don't linger past target validity while still batching rapid successive calls. As implemented in ego-lite, this avoids the complexity of heartbeat detection or reference counting.

### What happens when the event buffer reaches 10,000 entries?

The oldest events are dropped to maintain the limit. The runtime uses `splice(0, events.length - MAX_BUFFERED_EVENTS)` at lines 86-90, keeping only the most recent entries. This preserves recent CDP history (network logs, console messages) without memory leaks during long-running automations.

### Can I configure the TTL or buffer size?

No—both `SESSION_TTL_MS` and `MAX_BUFFERED_EVENTS` are hard-coded constants in [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts). To change these values, you must modify the source and rebuild. The design prioritizes simplicity and predictable behavior over configurability.

### How do I detect if my session was invalidated?

There's no explicit callback. After `invalidateSession()` or automatic invalidation, the next CDP call will transparently create a new session through `ensureSession()`. For debugging, check `sessionId` before/after operations or enable logging at the transport layer to observe session transitions.