This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: bun-websocket-backpressure-drain-protocol-bun-1-2-websocke-598

Bun 1.2 WebSocket Backpressure TCP Drain Protocol

Protects real-time edge gateways from unconstrained heap exhaustion and process termination by enforcing Bun 1.2 WebSocket backpressure management. Mandates checking the byte return value of ServerWebSocket.send() and deferring additional writes using the socket drain lifecycle hook when the internal TCP buffer exceeds watermark thresholds.

Prohibited Anti-Pattern: Unchecked ServerWebSocket.send() Calls Triggering Unbounded Buffer Expansion and Out-Of-Memory Crashes

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Bun 1.2 WebSocket Backpressure TCP Drain Protocol - Protects real-time edge gateways from unconstrained heap exhaustion and process termination by enforcing Bun 1.2 WebSocket backpressure management. Mandates checking the byte return value of ServerWebSocket.send() and deferring additional writes using the socket drain lifecycle hook when the internal TCP buffer exceeds watermark thresholds.
globs: src/**/*.{ts,js}, server/**/*.{ts,js}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/bun-websocket-backpressure-drain-protocol-bun-1-2-websocke-598"
---

# Bun 1.2 WebSocket Backpressure TCP Drain Protocol

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Unchecked ServerWebSocket.send() Calls Triggering Unbounded Buffer Expansion and Out-Of-Memory Crashes

## System Constraints
You are a Principal Engineer enforcing Bun 1.2 WebSocket Backpressure TCP Drain Protocol. Mandate zero-copy payload streaming and strict backpressure adherence on all WebSocket implementations. Never allow fire-and-forget socket writes in high-throughput environments.

## Strict Guidelines
- Engineers MUST ALWAYS inspect the return value of ws.send(data), which represents the exact byte count queued into the socket buffer or dropped.
- Engineers MUST pause payload consumption and enqueue pending frames into an explicit bounded queue when ws.send() returns -1 or exceeds the defined high-watermark threshold (e.g., ws.bufferedAmount > 64KB).
- Engineers MUST NOT continuously push messages to a slow client inside tight loops without checking ws.bufferedAmount and awaiting the drain lifecycle hook.
- Services MUST implement the drain(ws) handler in the Bun.serve({ websocket: { ... } }) configuration to resume queued transmission when the kernel TCP send window clears.
- Components NEVER store unbounded outbound messages in memory; if a client's queued frames exceed the absolute hard limit (maxBackpressureBuffer), the server MUST immediately terminate the connection with ws.close(1008, 'Policy Violation: Backpressure Exceeded').

## Bad vs Good Implementations
### Naive Unbounded Loop vs. Drain-Aware Bounded Queue Protocol

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: ws.send() returns the byte count or status indicating buffer state. Ignoring this return value and the drain event causes the internal C++ write buffer to balloon uncontrollably, resulting in a silent process OOM crash under high network latency.
```typescript
import { serve } from 'bun';

serve({
  port: 8080,
  websocket: {
    message(ws, message) {
      // VIOLATION: Fire-and-forget streaming in a tight loop.
      // Ignores socket buffer saturation; causes unconstrained heap expansion on slow clients.
      for (let i = 0; i < 1_000_000; i++) {
        ws.send(`event-payload-${i}`);
      }
    },
  },
  fetch(req, server) {
    if (server.upgrade(req)) return;
    return new Response('Upgrade failed', { status: 400 });
  },
});
```

#### Production Standard (Correct)
> **Standard**: Tracks ws.bufferedAmount against a 64KB high watermark, safely queues overflow payloads in a bounded structure, and relies on Bun's native drain callback to resume transmission. It rigorously terminates connections that exceed 2MB to protect the edge gateway against heap exhaustion.
```typescript
import { serve, type ServerWebSocket } from 'bun';

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

const HIGH_WATERMARK_BYTES = 64 * 1024; // 64KB
const MAX_BUFFER_LIMIT_BYTES = 2 * 1024 * 1024; // 2MB Hard Limit

serve<SocketData>({
  port: 8080,
  websocket: {
    open(ws) {
      ws.data = { id: crypto.randomUUID(), queue: [], paused: false };
    },
    drain(ws) {
      // Invariant: Flush deferred queue when kernel TCP buffer clears
      while (ws.data.queue.length > 0) {
        if (ws.bufferedAmount >= HIGH_WATERMARK_BYTES) {
          return; // Remain paused
        }
        const nextPayload = ws.data.queue.shift()!;
        const written = ws.send(nextPayload);
        if (written === -1) {
          ws.data.queue.unshift(nextPayload);
          return;
        }
      }
      ws.data.paused = false;
    },
    message(ws, message) {
      const payload = Buffer.from(typeof message === 'string' ? message : message);
      
      if (ws.bufferedAmount + payload.byteLength > MAX_BUFFER_LIMIT_BYTES) {
        // Invariant: Terminate rogue/slow clients violating resource boundaries
        ws.close(1008, 'Backpressure threshold exceeded');
        return;
      }

      if (ws.data.paused || ws.bufferedAmount >= HIGH_WATERMARK_BYTES) {
        ws.data.paused = true;
        ws.data.queue.push(payload);
        return;
      }

      const sentBytes = ws.send(payload);
      if (sentBytes === -1 || ws.bufferedAmount >= HIGH_WATERMARK_BYTES) {
        ws.data.paused = true;
      }
    },
    close(ws) {
      ws.data.queue.length = 0;
    }
  },
  fetch(req, server) {
    if (server.upgrade(req, { data: { id: '', queue: [], paused: false } })) return;
    return new Response('Upgrade failed', { status: 400 });
  },
});
```

Recommended MCP Servers (mcp-serverlist.com)

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

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Bun 1.2 WebSocket Backpressure TCP Drain Protocol

Bun 1.2 WebSocket Backpressure TCP Drain Protocol defines an industrial-grade behavioral standard for backend engineering. Protects real-time edge gateways from unconstrained heap exhaustion and process termination by enforcing Bun 1.2 WebSocket backpressure management. Mandates checking the byte return value of ServerWebSocket.send() and deferring additional writes using the socket drain lifecycle hook when the internal TCP buffer exceeds watermark thresholds. 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: Unchecked ServerWebSocket.send() Calls Triggering Unbounded Buffer Expansion and Out-Of-Memory Crashes 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 DriftUnchecked ServerWebSocket.send() Calls Triggering Unbounded Buffer Expansion and Out-Of-Memory CrashesCritical
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 inspect the return value of ws.send(data), which represents the exact byte count queued into the socket buffer or dropped.

Engineers MUST ALWAYS inspect the return value of ws.send(data), which represents the exact byte count queued into the socket buffer or dropped.

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 pause payload consumption and enqueue pending frames into an explicit bounded queue when ws.send() returns -1 or exceeds the defined high-watermark threshold (e.g., ws.bufferedAmount > 64KB).

Engineers MUST pause payload consumption and enqueue pending frames into an explicit bounded queue when ws.send() returns -1 or exceeds the defined high-watermark threshold (e.g., ws.bufferedAmount > 64KB).

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

Engineers MUST NOT continuously push messages to a slow client inside tight loops without checking ws.bufferedAmount and awaiting the drain lifecycle hook.

Engineers MUST NOT continuously push messages to a slow client inside tight loops without checking ws.bufferedAmount and awaiting the drain lifecycle hook.

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

Services MUST implement the drain(ws) handler in the Bun.serve({ websocket

Services MUST implement the drain(ws) handler in the Bun.serve({ websocket: { ... } }) configuration to resume queued transmission when the kernel TCP send window clears.

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 store unbounded outbound messages in memory

Components NEVER store unbounded outbound messages in memory; if a client's queued frames exceed the absolute hard limit (maxBackpressureBuffer), the server MUST immediately terminate the connection with ws.close(1008, 'Policy Violation: Backpressure Exceeded').

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 WebSocket Backpressure TCP Drain Protocol critical for AI coding assistants?

Protects real-time edge gateways from unconstrained heap exhaustion and process termination by enforcing Bun 1.2 WebSocket backpressure management. Mandates checking the byte return value of ServerWebSocket.send() and deferring additional writes using the socket drain lifecycle hook when the internal TCP buffer exceeds watermark thresholds. 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 (Unchecked ServerWebSocket.send() Calls Triggering Unbounded Buffer Expansion and Out-Of-Memory Crashes) 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