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

Bun 1.2 Native WebSocket Kernel Backpressure and Drain Boundary Standard

Enforces backpressure handling for Bun native WebSockets by strictly evaluating the byte-length return value of ws.send() and deferring dispatches during buffer saturation. Failure to park consumer-bound queues until the native drain() callback fires triggers unbounded heap growth and fatal OOM conditions under slow-client or high-throughput stalls.

Prohibited Anti-Pattern: Unbounded fire-and-forget WebSocket broadcasting ignoring ws.send() buffer backpressure and drain lifecycles

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Bun 1.2 Native WebSocket Kernel Backpressure and Drain Boundary Standard - Enforces backpressure handling for Bun native WebSockets by strictly evaluating the byte-length return value of ws.send() and deferring dispatches during buffer saturation. Failure to park consumer-bound queues until the native drain() callback fires triggers unbounded heap growth and fatal OOM conditions under slow-client or high-throughput stalls.
globs: src/**/*.ts, server/**/*.ts, services/**/*.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/bun-websocket-kernel-backpressure-drain-boundary"
---

# Bun 1.2 Native WebSocket Kernel Backpressure and Drain Boundary Standard

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Unbounded fire-and-forget WebSocket broadcasting ignoring ws.send() buffer backpressure and drain lifecycles

## System Constraints
You are a Principal Backend Systems Architect enforcing memory boundaries and zero-allocation backpressure flows in Bun 1.2 native WebSocket servers. Mandate that every WebSocket transmission evaluates kernel buffer saturation via ws.send() return codes, integrates native drain event lifecycle hooks, and enforces connection termination when client drain timeouts are exceeded.

## Strict Guidelines
- Engineers MUST ALWAYS inspect the numerical return value of `ws.send(data)`: a return value of -1 denotes dropping/failure, 0 denotes complete kernel transmission, and any positive integer (> 0) denotes the number of bytes queued in native user-space memory due to kernel backpressure.
- Engineers MUST pause dispatch loops and register a client-bound egress queue when `ws.send(data) > 0` or when `ws.isBackpressured` evaluates to true.
- Services MUST implement the `drain(ws)` handler in the `Bun.serve({ websocket: { ... } })` configuration to resume suspended queues and flush buffered frames only when the kernel buffer clears.
- Engineers MUST NOT maintain unbounded in-memory queues per socket; queues MUST enforce a maximum byte limit (e.g., 2MB) and immediately terminate stalled slow consumers via `ws.close(1008, 'Policy Violation: Backpressure Exceeded')`.
- Engineers MUST NOT rely on high-level pub/sub abstractions without verifying that individual socket subscriptions respect backpressure drain boundaries under asymmetric network topologies.

## Bad vs Good Implementations
### Flawed Naive Broadcast vs. Kernel-Aware Backpressured Drain Loop

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Ignoring the return value of ws.send() allows fast producers to saturate native kernel socket buffers. As Bun queues unsent payloads in user-space C++ memory without an upper boundary or suspension mechanism, memory grows unboundedly until the OS kills the process.
```typescript
import { ServerWebSocket } from 'bun';

interface ClientData {
  id: string;
}

// ANTI-PATTERN: Blind iteration and dispatch ignores ws.send() return code.
// When a slow client stalls, unacknowledged frames accumulate in Bun's internal C++ heap
// until the process suffers from out-of-memory termination.
export function broadcastMetrics(clients: Set<ServerWebSocket<ClientData>>, payload: Uint8Array): void {
  for (const ws of clients) {
    // ws.send returns the number of queued bytes (>0 indicates backpressure saturation)
    ws.send(payload);
  }
}
```

#### Production Standard (Correct)
> **Standard**: Evaluates ws.send() byte return codes, enforces a bounded 2MB backpressure threshold to drop recalcitrant consumers, and leverages the native Bun drain() lifecycle hook to systematically flush pending frames without user-space buffer bloat.
```typescript
import { ServerWebSocket, serve } from 'bun';

interface SocketState {
  id: string;
  queue: Uint8Array[];
  queuedBytes: number;
}

const MAX_BUFFERED_BYTES = 2 * 1024 * 1024; // 2MB hard ceiling per client

export function safeSend(ws: ServerWebSocket<SocketState>, data: Uint8Array): void {
  // If the socket already has un-drained queued chunks, buffer immediately
  if (ws.data.queue.length > 0) {
    enqueuePayload(ws, data);
    return;
  }

  const queued = ws.send(data);
  if (queued > 0) {
    // Kernel buffer saturated: positive integer indicates byte count buffered internally
    ws.data.queuedBytes += queued;
  } else if (queued === -1) {
    ws.close(1011, 'Socket write failure');
  }
}

function enqueuePayload(ws: ServerWebSocket<SocketState>, data: Uint8Array): void {
  if (ws.data.queuedBytes + data.byteLength > MAX_BUFFERED_BYTES) {
    ws.close(1008, 'Policy Violation: Backpressure ceiling exceeded');
    ws.data.queue.length = 0;
    ws.data.queuedBytes = 0;
    return;
  }
  ws.data.queue.push(data);
  ws.data.queuedBytes += data.byteLength;
}

export const server = serve<SocketState>({
  port: 3000,
  fetch(req, server) {
    if (server.upgrade(req, { data: { id: crypto.randomUUID(), queue: [], queuedBytes: 0 } })) {
      return;
    }
    return new Response('Expected WebSocket', { status: 400 });
  },
  websocket: {
    message(ws, message) {
      // Standard message ingress
    },
    drain(ws) {
      // Native kernel drain callback: socket is writable again
      while (ws.data.queue.length > 0) {
        const nextChunk = ws.data.queue[0];
        const queued = ws.send(nextChunk);

        if (queued > 0) {
          // Socket saturated again before exhausting queue; await next drain()
          return;
        }

        const flushed = ws.data.queue.shift();
        if (flushed) {
          ws.data.queuedBytes -= flushed.byteLength;
        }
      }
    },
    close(ws) {
      ws.data.queue.length = 0;
      ws.data.queuedBytes = 0;
    }
  }
});
```

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 Native WebSocket Kernel Backpressure and Drain Boundary Standard

Bun 1.2 Native WebSocket Kernel Backpressure and Drain Boundary Standard defines an industrial-grade behavioral standard for backend engineering. Enforces backpressure handling for Bun native WebSockets by strictly evaluating the byte-length return value of ws.send() and deferring dispatches during buffer saturation. Failure to park consumer-bound queues until the native drain() callback fires triggers unbounded heap growth and fatal OOM conditions under slow-client or high-throughput stalls. 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 WebSocket broadcasting ignoring ws.send() buffer backpressure and drain lifecycles 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 WebSocket broadcasting ignoring ws.send() buffer backpressure and drain lifecyclesCritical
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 numerical return value of `ws.send(data)`

Engineers MUST ALWAYS inspect the numerical return value of `ws.send(data)`: a return value of -1 denotes dropping/failure, 0 denotes complete kernel transmission, and any positive integer (> 0) denotes the number of bytes queued in native user-space memory due to kernel 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.
2

Engineers MUST pause dispatch loops and register a client-bound egress queue when `ws.send(data) > 0` or when `ws.isBackpressured` evaluates to true.

Engineers MUST pause dispatch loops and register a client-bound egress queue when `ws.send(data) > 0` or when `ws.isBackpressured` evaluates to true.

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)` handler in the `Bun.serve({ websocket

Services MUST implement the `drain(ws)` handler in the `Bun.serve({ websocket: { ... } })` configuration to resume suspended queues and flush buffered frames only when the kernel buffer 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.
4

Engineers MUST NOT maintain unbounded in-memory queues per socket

Engineers MUST NOT maintain unbounded in-memory queues per socket; queues MUST enforce a maximum byte limit (e.g., 2MB) and immediately terminate stalled slow consumers via `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.
5

Engineers MUST NOT rely on high-level pub/sub abstractions without verifying that individual socket subscriptions respect backpressure drain boundaries under asymmetric network topologies.

Engineers MUST NOT rely on high-level pub/sub abstractions without verifying that individual socket subscriptions respect backpressure drain boundaries under asymmetric network topologies.

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 Backpressure and Drain Boundary Standard critical for AI coding assistants?

Enforces backpressure handling for Bun native WebSockets by strictly evaluating the byte-length return value of ws.send() and deferring dispatches during buffer saturation. Failure to park consumer-bound queues until the native drain() callback fires triggers unbounded heap growth and fatal OOM conditions under slow-client or high-throughput stalls. 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 WebSocket broadcasting ignoring ws.send() buffer backpressure and drain lifecycles) 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