This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: connect-rpc-http3-flow-control-guardrail

Connect-RPC HTTP/3 Multiplexed Flow Control & Backpressure Invariant

Mandates strict synchronous backpressure, bounded stream buffering, and context-cancellation propagation across Connect-RPC bidirectional streams over HTTP/3. Prevents QUIC stream-level window starvation and unconstrained heap memory ballooning during high-concurrency browser-to-server multiplexing.

Prohibited Anti-Pattern: Unbounded Stream Ingestion and Detached Concurrent Yielding in Bidirectional RPC Handlers

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Connect-RPC HTTP/3 Multiplexed Flow Control & Backpressure Invariant - Mandates strict synchronous backpressure, bounded stream buffering, and context-cancellation propagation across Connect-RPC bidirectional streams over HTTP/3. Prevents QUIC stream-level window starvation and unconstrained heap memory ballooning during high-concurrency browser-to-server multiplexing.
globs: src/**/*.ts, src/**/service*.ts, src/**/rpc*.ts, src/**/router.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/connect-rpc-http3-flow-control-guardrail"
---

# Connect-RPC HTTP/3 Multiplexed Flow Control & Backpressure Invariant

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Unbounded Stream Ingestion and Detached Concurrent Yielding in Bidirectional RPC Handlers

## System Constraints
You are a Principal Engineer enforcing Connect-RPC HTTP/3 End-to-End Multiplexed Flow Control Guardrails. You must mandate end-to-end backpressure on all bidirectional and server-streaming RPC endpoints. Never permit unbounded asynchronous message queues, unthrottled iteration over incoming streams, or detached async tasks writing to a stream without honoring QUIC backpressure and context cancellation.

## Strict Guidelines
- Engineers MUST ALWAYS iterate over incoming `AsyncIterable<TReq>` using sequential consumption or strictly bounded concurrency queues with backpressure.
- Engineers MUST NOT detach processing into floating promises or unbounded in-memory queues (e.g., calling `void process(msg)` inside a `for await` loop).
- Code MUST continuously monitor `context.signal` and terminate stream loops immediately upon client abort or QUIC stream reset.
- Services MUST enforce high-water-mark limits on any intermediary transform pipeline before yielding back to the HTTP/3 transport.
- Components NEVER buffer unbounded numbers of protobuf messages in heap memory; processing must stall upstream reads when downstream writes hit flow-control limits.

## Bad vs Good Implementations
### Bidirectional Stream Handler with Flow-Control Backpressure vs Unbounded Push

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Consumes the request stream asynchronously without waiting for downstream transmission, pushing onto an unbounded array. When the HTTP/3 QUIC stream flow-control window fills, `yield` blocks or messages pile up in `pendingMessages`, causing heap memory exhaustion.
```typescript
import { HandlerContext } from '@connectrpc/connect';
import { ChatRequest, ChatResponse } from './gen/chat_pb.js';

export async function* chatStream(
  reqStream: AsyncIterable<ChatRequest>,
  context: HandlerContext
): AsyncIterable<ChatResponse> {
  const pendingMessages: ChatResponse[] = [];

  // ANTI-PATTERN: Consumes incoming stream without backpressure,
  // detaching async tasks and accumulating responses in an unbounded array.
  // Under HTTP/3, slow clients cause pendingMessages to grow indefinitely, causing OOM.
  (async () => {
    for await (const req of reqStream) {
      void processMessageAsync(req).then((res) => {
        pendingMessages.push(res);
      });
    }
  })();

  while (!context.signal.aborted) {
    if (pendingMessages.length > 0) {
      const msg = pendingMessages.shift()!;
      yield msg;
    } else {
      await new Promise((resolve) => setTimeout(resolve, 10));
    }
  }
}

async function processMessageAsync(req: ChatRequest): Promise<ChatResponse> {
  return new ChatResponse({ reply: `Echo: ${req.message}` });
}
```

#### Production Standard (Correct)
> **Standard**: Enforces synchronous 1-to-1 backpressure using direct `for await` iteration and sequential `yield`. The incoming stream is paused whenever downstream QUIC stream buffers block on transport-level flow-control windows, and `context.signal` terminates processing on client disconnection.
```typescript
import { HandlerContext } from '@connectrpc/connect';
import { ChatRequest, ChatResponse } from './gen/chat_pb.js';

export async function* chatStream(
  reqStream: AsyncIterable<ChatRequest>,
  context: HandlerContext
): AsyncIterable<ChatResponse> {
  // INVARIANT: Sequential pull-push model preserves end-to-end backpressure.
  // Reads only advance when the previous message has been flushed into the QUIC stream buffer.
  for await (const req of reqStream) {
    if (context.signal.aborted) {
      break;
    }

    const response = await processMessage(req, context.signal);

    // Flow control: yield directly awaits transport buffer availability
    yield response;
  }
}

async function processMessage(req: ChatRequest, signal: AbortSignal): Promise<ChatResponse> {
  if (signal.aborted) {
    throw signal.reason;
  }
  return new ChatResponse({ reply: `Echo: ${req.message}` });
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Connect-RPC HTTP/3 Multiplexed Flow Control & Backpressure Invariant

Connect-RPC HTTP/3 Multiplexed Flow Control & Backpressure Invariant defines an industrial-grade behavioral standard for backend engineering. Mandates strict synchronous backpressure, bounded stream buffering, and context-cancellation propagation across Connect-RPC bidirectional streams over HTTP/3. Prevents QUIC stream-level window starvation and unconstrained heap memory ballooning during high-concurrency browser-to-server multiplexing. 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 Stream Ingestion and Detached Concurrent Yielding in Bidirectional RPC Handlers 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 Stream Ingestion and Detached Concurrent Yielding in Bidirectional RPC HandlersCritical
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 iterate over incoming `AsyncIterable<TReq>` using sequential consumption or strictly bounded concurrency queues with backpressure.

Engineers MUST ALWAYS iterate over incoming `AsyncIterable<TReq>` using sequential consumption or strictly bounded concurrency queues with 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 NOT detach processing into floating promises or unbounded in-memory queues (e.g., calling `void process(msg)` inside a `for await` loop).

Engineers MUST NOT detach processing into floating promises or unbounded in-memory queues (e.g., calling `void process(msg)` inside a `for await` loop).

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

Code MUST continuously monitor `context.signal` and terminate stream loops immediately upon client abort or QUIC stream reset.

Code MUST continuously monitor `context.signal` and terminate stream loops immediately upon client abort or QUIC stream reset.

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 enforce high-water-mark limits on any intermediary transform pipeline before yielding back to the HTTP/3 transport.

Services MUST enforce high-water-mark limits on any intermediary transform pipeline before yielding back to the HTTP/3 transport.

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 buffer unbounded numbers of protobuf messages in heap memory

Components NEVER buffer unbounded numbers of protobuf messages in heap memory; processing must stall upstream reads when downstream writes hit flow-control limits.

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 Connect-RPC HTTP/3 Multiplexed Flow Control & Backpressure Invariant critical for AI coding assistants?

Mandates strict synchronous backpressure, bounded stream buffering, and context-cancellation propagation across Connect-RPC bidirectional streams over HTTP/3. Prevents QUIC stream-level window starvation and unconstrained heap memory ballooning during high-concurrency browser-to-server multiplexing. 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 Stream Ingestion and Detached Concurrent Yielding in Bidirectional RPC Handlers) 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

Connect-RPC