This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
frontendcritical PriorityID: nextjs15-ppr-dynamic-hole-timeout-standard

Next.js 15 PPR Dynamic Hole Streaming Flush-Timeout Standard

Enforces deterministic flush timeouts and boundary encapsulation for dynamic streaming holes in Next.js 15 Partial Prerendering (PPR). Prevents high-latency downstream microservices and slow dynamic queries from blocking early static shell edge delivery or stalling HTTP streaming responses. Mandates AbortController timeouts, granular React Suspense fallback boundaries, and non-blocking error fallbacks.

Prohibited Anti-Pattern: Unbounded Async Hole Execution Stalling Edge Shell Delivery and HTTP Streaming

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Next.js 15 PPR Dynamic Hole Streaming Flush-Timeout Standard - Enforces deterministic flush timeouts and boundary encapsulation for dynamic streaming holes in Next.js 15 Partial Prerendering (PPR). Prevents high-latency downstream microservices and slow dynamic queries from blocking early static shell edge delivery or stalling HTTP streaming responses. Mandates AbortController timeouts, granular React Suspense fallback boundaries, and non-blocking error fallbacks.
globs: src/app/**/*.{ts,tsx}, app/**/*.{ts,tsx}, src/components/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/nextjs15-ppr-dynamic-hole-timeout-standard"
---

# Next.js 15 PPR Dynamic Hole Streaming Flush-Timeout Standard

> **Severity**: CRITICAL | **Category**: frontend
> **Anti-Pattern Warning**: Unbounded Async Hole Execution Stalling Edge Shell Delivery and HTTP Streaming

## System Constraints
You are a Principal Software Architect enforcing production reliability standards for Next.js 15 Partial Prerendering (PPR). Your objective is to ensure that dynamic holes embedded within static shells never degrade edge-delivery guarantees or stall response chunk delivery. You must mandate strict per-fetch and per-component timeouts via AbortSignal, enforce atomic Suspense wrappers, and guarantee graceful fallback degradation for every dynamic hole.

## Strict Guidelines
- Engineers MUST ALWAYS isolate every dynamic hole in Next.js 15 PPR inside an independent React <Suspense> boundary with a lightweight, pre-rendered fallback skeleton.
- Engineers MUST NOT invoke unbounded asynchronous calls or external microservice queries inside dynamic components without an explicit AbortSignal.timeout() guardrail.
- Dynamic data fetching within streaming holes MUST enforce a strict flush ceiling (maximum 1500ms, recommended <= 800ms) before aborting and degrading to cached or empty fallback states.
- Components NEVER execute top-level awaits across multiple disparate dynamic domains; dynamic fetch operations MUST be parallelized or individually isolated in sub-tree Suspense boundaries.
- Services MUST catch dynamic timeout exceptions internally within the dynamic hole component boundary to prevent throwing unhandled rejections that terminate the entire HTTP chunk stream.
- Engineers MUST NOT place dynamic components (such as cookies(), headers(), or non-cached fetch) outside Suspense boundaries when experimental.ppr = true is enabled.

## Bad vs Good Implementations
### Unbounded Microservice Fetch inside Dynamic PPR Hole vs. Resilient Timeout-Guarded Stream Hole

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: When using PPR, this dynamic hole awaits an unbounded external fetch. If the downstream microservice experiences high latency or hangs, the entire HTTP streaming response is stalled, inflating Time To First Byte (TTFB) or freezing chunk rendering. An unhandled rejection terminates the connection without rendering an inline fallback.
```typescript
import { cookies } from 'next/headers';

// ANTI-PATTERN: Unbounded dynamic hole that blocks shell streaming if the service stalls,
// lacks an explicit AbortSignal timeout, and fails to handle fetch rejection locally.
export async function UserRecommendations() {
  const sessionToken = (await cookies()).get('session')?.value;
  
  // Stalls the dynamic hole stream indefinitely if recommendation-service hangs
  const res = await fetch('https://api.internal.corp/recommendations', {
    headers: { Authorization: `Bearer ${sessionToken}` },
    cache: 'no-store'
  });
  const recommendations = await res.json();

  return (
    <ul className="rec-list">
      {recommendations.map((item: { id: string; title: string }) => (
        <li key={item.id}>{item.title}</li>
      ))}
    </ul>
  );
}
```

#### Production Standard (Correct)
> **Standard**: The component encapsulates dynamic data within a bounded timeout via AbortSignal.timeout(800). If the downstream service exceeds the timeout ceiling, the error is trapped within the hole, returning a degraded fallback array instead of stalling or crashing the HTTP stream. An explicit Suspense boundary guarantees the static shell flushes immediately from edge cache.
```typescript
import { cookies } from 'next/headers';
import { Suspense } from 'react';

interface Recommendation {
  id: string;
  title: string;
}

const DYNAMIC_HOLE_TIMEOUT_MS = 800;

async function fetchRecommendationsWithTimeout(token?: string): Promise<Recommendation[]> {
  if (!token) return [];
  
  try {
    const res = await fetch('https://api.internal.corp/recommendations', {
      headers: { Authorization: `Bearer ${token}` },
      cache: 'no-store',
      signal: AbortSignal.timeout(DYNAMIC_HOLE_TIMEOUT_MS)
    });
    
    if (!res.ok) throw new Error(`Fetch failed with status ${res.status}`);
    return (await res.json()) as Recommendation[];
  } catch (error) {
    // Gracefully degrade dynamic hole on timeout or downstream failure
    console.error('Dynamic hole flush timeout / failure, degrading gracefully:', error);
    return [];
  }
}

async function RecommendationsContent() {
  const cookieStore = await cookies();
  const sessionToken = cookieStore.get('session')?.value;
  const items = await fetchRecommendationsWithTimeout(sessionToken);

  if (items.length === 0) {
    return <p className="rec-empty">No recommendations currently available.</p>;
  }

  return (
    <ul className="rec-list">
      {items.map((item) => (
        <li key={item.id}>{item.title}</li>
      ))}
    </ul>
  );
}

export function UserRecommendations() {
  return (
    <Suspense fallback={<div className="h-12 w-full animate-pulse bg-slate-200 rounded" />}>
      <RecommendationsContent />
    </Suspense>
  );
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Next.js 15 PPR Dynamic Hole Streaming Flush-Timeout Standard

Next.js 15 PPR Dynamic Hole Streaming Flush-Timeout Standard defines an industrial-grade behavioral standard for frontend engineering. Enforces deterministic flush timeouts and boundary encapsulation for dynamic streaming holes in Next.js 15 Partial Prerendering (PPR). Prevents high-latency downstream microservices and slow dynamic queries from blocking early static shell edge delivery or stalling HTTP streaming responses. Mandates AbortController timeouts, granular React Suspense fallback boundaries, and non-blocking error fallbacks. 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 Async Hole Execution Stalling Edge Shell Delivery and HTTP Streaming 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 Async Hole Execution Stalling Edge Shell Delivery and HTTP StreamingCritical
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 isolate every dynamic hole in Next.js 15 PPR inside an independent React <Suspense> boundary with a lightweight, pre-rendered fallback skeleton.

Engineers MUST ALWAYS isolate every dynamic hole in Next.js 15 PPR inside an independent React <Suspense> boundary with a lightweight, pre-rendered fallback skeleton.

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 invoke unbounded asynchronous calls or external microservice queries inside dynamic components without an explicit AbortSignal.timeout() guardrail.

Engineers MUST NOT invoke unbounded asynchronous calls or external microservice queries inside dynamic components without an explicit AbortSignal.timeout() guardrail.

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

Dynamic data fetching within streaming holes MUST enforce a strict flush ceiling (maximum 1500ms, recommended <= 800ms) before aborting and degrading to cached or empty fallback states.

Dynamic data fetching within streaming holes MUST enforce a strict flush ceiling (maximum 1500ms, recommended <= 800ms) before aborting and degrading to cached or empty fallback states.

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

Components NEVER execute top-level awaits across multiple disparate dynamic domains

Components NEVER execute top-level awaits across multiple disparate dynamic domains; dynamic fetch operations MUST be parallelized or individually isolated in sub-tree Suspense boundaries.

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

Services MUST catch dynamic timeout exceptions internally within the dynamic hole component boundary to prevent throwing unhandled rejections that terminate the entire HTTP chunk stream.

Services MUST catch dynamic timeout exceptions internally within the dynamic hole component boundary to prevent throwing unhandled rejections that terminate the entire HTTP chunk stream.

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.
6

Engineers MUST NOT place dynamic components (such as cookies(), headers(), or non-cached fetch) outside Suspense boundaries when experimental.ppr = true is enabled.

Engineers MUST NOT place dynamic components (such as cookies(), headers(), or non-cached fetch) outside Suspense boundaries when experimental.ppr = true is enabled.

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 Next.js 15 PPR Dynamic Hole Streaming Flush-Timeout Standard critical for AI coding assistants?

Enforces deterministic flush timeouts and boundary encapsulation for dynamic streaming holes in Next.js 15 Partial Prerendering (PPR). Prevents high-latency downstream microservices and slow dynamic queries from blocking early static shell edge delivery or stalling HTTP streaming responses. Mandates AbortController timeouts, granular React Suspense fallback boundaries, and non-blocking error fallbacks. 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 Async Hole Execution Stalling Edge Shell Delivery and HTTP Streaming) 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.

Related FRONTEND Rules

View all rules →
frontend
119

SolidStart 1.0 Server Functions & Async Boundaries Production Standard

SolidStart 1.0 relies on the Vinxi bundler to split `server$` closures into independent HTTP POST RPC endpoints. Direct lexical closure over client signals within `server$` scopes or failure to demarcate async boundaries with `<Suspense>` causes silent serialization failures, client-bundle secret leaks, and SSR hydration mismatches. Enforcing strict parameter passing, runtime input validation, and Solid async primitives maintains security and fine-grained reactivity across network boundaries.

frontend
119

Astro 5 Actions & Content Layer Production Standard

Enforces strict type safety and architectural correctness for Astro 5 Server Actions and the zero-waterfall Content Layer API. Prevents runtime contract mismatches, hydration mismatches, and unhandled mutation exceptions across dynamic and prerendered boundaries. Failure to follow these patterns leads to silent data fetching waterfalls, build-time cache corruptions, and unhandled server action exceptions.

frontend
51

Nuxt 4 Nitro Server Engine & Shared Directory Production Standard

Nuxt 4 enforces strict boundary segregation between client UI in the app/ directory, backend endpoints in server/, and universal contracts in shared/. Violating cross-boundary isolation or maintaining module-scoped state in Nitro server handlers causes catastrophic cross-request data corruption and hydration mismatches under concurrent production traffic. Architects must enforce request-isolated H3 event contexts, universal serialization schemas, and strict path-alias boundaries.

1 Rule in Stack

Next.js