This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: bun-websocket-kernel-backpressure-guardrail

Bun 1.2 Native WebSocket Kernel TCP Backpressure & Drain Invariants

Enforces mandatory TCP backpressure handling and kernel socket drainage monitoring for Bun 1.2+ native WebSockets. Prevents catastrophic heap exhaustion and silent message dropping under bursty bidirectional workloads by integrating the native drain lifecycle hook and bounded per-socket write queues.

Prohibited Anti-Pattern: Unbounded Fire-and-Forget ws.send() Broadcasting Leading to Kernel Buffer Exhaustion and Heap OOM

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Bun 1.2 Native WebSocket Kernel TCP Backpressure & Drain Invariants - Enforces mandatory TCP backpressure handling and kernel socket drainage monitoring for Bun 1.2+ native WebSockets. Prevents catastrophic heap exhaustion and silent message dropping under bursty bidirectional workloads by integrating the native drain lifecycle hook and bounded per-socket write queues.
globs: src/**/*.{ts,tsx}, server/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/bun-websocket-kernel-backpressure-guardrail"
---

# Bun 1.2 Native WebSocket Kernel TCP Backpressure & Drain Invariants

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Unbounded Fire-and-Forget ws.send() Broadcasting Leading to Kernel Buffer Exhaustion and Heap OOM

## System Constraints
You are a Principal Backend Systems Architect enforcing strict Bun 1.2 native WebSocket backpressure invariants. Bun's high-performance native WebSocket implementation operates directly on native TCP sockets; sending data faster than clients can consume without inspecting ws.send() return codes or bufferedAmount causes silent frame dropping, buffer memory bloat, or catastrophic heap exhaustion. Mandate rigorous drain handling and bounded queues.

## Strict Guidelines
- Engineers MUST ALWAYS evaluate the return value of Bun's `ws.send()` (or check `ws.bufferedAmount`) before enqueuing additional outbound messages.
- Engineers MUST NOT call `ws.send()` in tight loops or fanout broadcasts without a pausing mechanism when the socket enters backpressure.
- Services MUST implement the `drain(ws)` lifecycle callback in `Bun.serve({ websocket: { drain(ws) { ... } } })` to flush buffered queues when the underlying TCP socket drains.
- Code SHOULD enforce hard per-connection memory limits, forcibly terminating slow or stalling clients (`ws.close(1008, 'Buffer overflow')`) when `ws.bufferedAmount` breaches threshold invariants.
- Components NEVER assume `ws.send()` synchronously delivers bytes over the wire; it queues into kernel buffers subject to OS-level TCP window constraints.

## Bad vs Good Implementations
### Unbounded Fanout Broadcast vs. Backpressure-Aware Bounded Queue with Native Drain

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Iterating over sockets and blindly executing ws.send() ignores backpressure signals. If a client has a constrained TCP window or high latency, un-drained frames accumulate in native memory buffers, resulting in silent message drops or abrupt V8/JavaScriptCore heap exhaustion crashes under burst traffic.
```typescript
import { ServerWebSocket } from "bun";

const clients = new Set<ServerWebSocket<unknown>>();

Bun.serve({
  port: 3000,
  fetch(req, server) {
    if (server.upgrade(req)) return;
    return new Response("Upgrade failed", { status: 400 });
  },
  websocket: {
    open(ws) {
      clients.add(ws);
    },
    close(ws) {
      clients.delete(ws);
    },
    message(ws, message) {
      // CRITICAL FLAW: Blindly broadcasting to all clients without checking return codes
      // or bufferedAmount. A single slow consumer on a high-throughput stream causes
      // memory accumulation in userland or silent kernel drop cascades.
      for (const client of clients) {
        client.send(message);
      }
    },
  },
});
```

#### Production Standard (Correct)
> **Standard**: Implements proper backpressure invariants: checks client.bufferedAmount to detect backpressure, enqueues pending messages into a bounded buffer, respects the native drain lifecycle event to resume transmission when socket buffers empty, and forcibly evicts non-responsive clients before memory thresholds are violated.
```typescript
import { ServerWebSocket } from "bun";

interface SocketData {
  id: string;
  queue: Uint8Array[];
  isBackpressured: boolean;
}

const MAX_BUFFERED_BYTES = 512 * 1024; // 512 KB threshold for slow client eviction
const clients = new Set<ServerWebSocket<SocketData>>();

function flushQueue(ws: ServerWebSocket<SocketData>): boolean {
  while (ws.data.queue.length > 0) {
    const nextMsg = ws.data.queue[0];
    // In Bun, ws.send returns the number of bytes sent or queued.
    // A return of 0 or < byte length indicates kernel backpressure.
    const bytesSent = ws.send(nextMsg);
    if (bytesSent <= 0 || ws.bufferedAmount > 0) {
      ws.data.isBackpressured = true;
      return false;
    }
    ws.data.queue.shift();
  }
  ws.data.isBackpressured = false;
  return true;
}

Bun.serve<SocketData>({
  port: 3000,
  fetch(req, server) {
    const upgraded = server.upgrade(req, {
      data: {
        id: crypto.randomUUID(),
        queue: [],
        isBackpressured: false,
      },
    });
    return upgraded ? undefined : new Response("Upgrade failed", { status: 400 });
  },
  websocket: {
    open(ws) {
      clients.add(ws);
    },
    close(ws) {
      clients.delete(ws);
      ws.data.queue.length = 0;
    },
    drain(ws) {
      // Mandatory: Native callback invoked when kernel TCP socket drains
      flushQueue(ws);
    },
    message(ws, message) {
      const payload = typeof message === "string" ? Buffer.from(message) : new Uint8Array(message as ArrayBuffer);

      for (const client of clients) {
        if (client.bufferedAmount > MAX_BUFFERED_BYTES) {
          client.close(1008, "Backpressure buffer exceeded: Slow consumer evicted");
          clients.delete(client);
          continue;
        }

        if (client.data.isBackpressured || client.data.queue.length > 0) {
          client.data.queue.push(payload);
        } else {
          const sent = client.send(payload);
          if (sent <= 0 || client.bufferedAmount > 0) {
            client.data.isBackpressured = true;
            client.data.queue.push(payload);
          }
        }
      }
    },
  },
});
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Bun 1.2 Native WebSocket Kernel TCP Backpressure & Drain Invariants

Bun 1.2 Native WebSocket Kernel TCP Backpressure & Drain Invariants defines an industrial-grade behavioral standard for backend engineering. Enforces mandatory TCP backpressure handling and kernel socket drainage monitoring for Bun 1.2+ native WebSockets. Prevents catastrophic heap exhaustion and silent message dropping under bursty bidirectional workloads by integrating the native drain lifecycle hook and bounded per-socket write queues. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Unbounded Fire-and-Forget ws.send() Broadcasting Leading to Kernel Buffer Exhaustion and Heap OOM Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftUnbounded Fire-and-Forget ws.send() Broadcasting Leading to Kernel Buffer Exhaustion and Heap OOMCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS evaluate the return value of Bun's `ws.send()` (or check `ws.bufferedAmount`) before enqueuing additional outbound messages.

Engineers MUST ALWAYS evaluate the return value of Bun's `ws.send()` (or check `ws.bufferedAmount`) before enqueuing additional outbound messages.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NOT call `ws.send()` in tight loops or fanout broadcasts without a pausing mechanism when the socket enters backpressure.

Engineers MUST NOT call `ws.send()` in tight loops or fanout broadcasts without a pausing mechanism when the socket enters backpressure.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Services MUST implement the `drain(ws)` lifecycle callback in `Bun.serve({ websocket

Services MUST implement the `drain(ws)` lifecycle callback in `Bun.serve({ websocket: { drain(ws) { ... } } })` to flush buffered queues when the underlying TCP socket drains.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Code SHOULD enforce hard per-connection memory limits, forcibly terminating slow or stalling clients (`ws.close(1008, 'Buffer overflow')`) when `ws.bufferedAmount` breaches threshold invariants.

Code SHOULD enforce hard per-connection memory limits, forcibly terminating slow or stalling clients (`ws.close(1008, 'Buffer overflow')`) when `ws.bufferedAmount` breaches threshold invariants.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Components NEVER assume `ws.send()` synchronously delivers bytes over the wire

Components NEVER assume `ws.send()` synchronously delivers bytes over the wire; it queues into kernel buffers subject to OS-level TCP window constraints.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Bun 1.2 Native WebSocket Kernel TCP Backpressure & Drain Invariants critical for AI coding assistants?

Enforces mandatory TCP backpressure handling and kernel socket drainage monitoring for Bun 1.2+ native WebSockets. Prevents catastrophic heap exhaustion and silent message dropping under bursty bidirectional workloads by integrating the native drain lifecycle hook and bounded per-socket write queues. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Unbounded Fire-and-Forget ws.send() Broadcasting Leading to Kernel Buffer Exhaustion and Heap OOM) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

Bun