This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
frontendcritical PriorityID: nextjs-15-dynamic-io-use-cache-tag-invalidation

Next.js 15 Dynamic I/O & 'use cache' Cryptographic Boundary Standard

Enforces strict tenant isolation and deterministic cache tagging under Next.js 15 Dynamic I/O architecture. Mandates that all cached execution scopes using the 'use cache' directive bind cryptographic, tenant-scoped cache tags and cacheLife profiles, eliminating multi-tenant data bleed across prerendered edge runtimes and persistent cache stores.

Prohibited Anti-Pattern: Global Unscoped 'use cache' Directives Causing Multi-Tenant Cache Pollution and Cross-Tenant Data Leaks

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Next.js 15 Dynamic I/O & 'use cache' Cryptographic Boundary Standard - Enforces strict tenant isolation and deterministic cache tagging under Next.js 15 Dynamic I/O architecture. Mandates that all cached execution scopes using the 'use cache' directive bind cryptographic, tenant-scoped cache tags and cacheLife profiles, eliminating multi-tenant data bleed across prerendered edge runtimes and persistent cache stores.
globs: src/app/**/*.{ts,tsx}, src/lib/**/*.{ts,tsx}, src/services/**/*.{ts,tsx}, app/**/*.{ts,tsx}, lib/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/nextjs-15-dynamic-io-use-cache-tag-invalidation"
---

# Next.js 15 Dynamic I/O & 'use cache' Cryptographic Boundary Standard

> **Severity**: CRITICAL | **Category**: frontend
> **Anti-Pattern Warning**: Global Unscoped 'use cache' Directives Causing Multi-Tenant Cache Pollution and Cross-Tenant Data Leaks

## System Constraints
You are a Principal Software Architect enforcing Next.js 15 Dynamic I/O & 'use cache' Tag Invalidation standards. Dynamic I/O makes asynchronous runtime data access dynamic by default, requiring explicit caching boundaries. You must reject any 'use cache' boundary that lacks explicit tenant-keyed cacheTag identifiers, deterministic cacheLife declarations, or uses unhashed raw multi-tenant parameters. Guarantee that all cache revalidation targets precise cryptographic tags rather than ambient, global routes.

## Strict Guidelines
- Engineers MUST ALWAYS pair the 'use cache' directive with 'cacheTag' calls that include an explicit, verified tenant or user ID prefix.
- Engineers MUST ALWAYS declare an explicit 'cacheLife' profile (e.g., 'minutes', 'hours', or custom presets) within every 'use cache' scope to avoid fallback retention hazards.
- Engineers MUST NEVER place the 'use cache' directive in a component or function containing ambient dynamic data access (e.g., headers(), cookies()) without deriving a cryptographic cache-key argument from those primitives.
- Code SHOULD isolate cached queries into dedicated, pure data-access layer (DAL) helper functions rather than inlining 'use cache' directly into root RSC layouts or pages.
- Services MUST revalidate cached data using 'revalidateTag' targeting the exact deterministic key format: `tenant:${tenantId}:${entity}:${entityId}`.
- Components NEVER render user-private data derived from a shared global cache tag that lacks tenant demarcation.

## Bad vs Good Implementations
### Unscoped vs Cryptographically Scoped 'use cache' Boundary

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Using an unscoped cache tag ('invoices') causes cross-tenant collisions and data contamination in the shared Next.js 15 data cache. When one tenant triggers revalidation, all tenant caches are purged; worse, dynamic I/O memoization may return tenant A's payload to tenant B if function inputs are flattened or mishandled in the cache layer.
```typescript
import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache';
import { db } from '@/lib/db';

// ANTI-PATTERN: 'use cache' on function fetching tenant data without tenant-scoped cacheTag
export async function getCustomerInvoices(tenantId: string) {
  'use cache';
  cacheLife('hours');
  cacheTag('invoices'); // Global tag: All tenants share and invalidate the exact same cache entry
  
  return await db.invoices.findMany({
    where: { tenantId },
  });
}
```

#### Production Standard (Correct)
> **Standard**: The cache tag is strictly bound to the hashed tenant identifier via deterministic tag synthesis. Dynamic I/O will compartmentalize this cache slice, preventing tenant data contamination across edge nodes and ensuring 'revalidateTag' invalidates only the requesting tenant's cache slice.
```typescript
import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache';
import { createHash } from 'node:crypto';
import { db } from '@/lib/db';

function getTenantTag(tenantId: string, entity: string): string {
  const hashedId = createHash('sha256').update(tenantId).digest('hex').slice(0, 16);
  return `tenant:${hashedId}:${entity}`;
}

// PRODUCTION FIX: Cryptographically bound cacheTag with strict parameter isolation
export async function getCustomerInvoices(tenantId: string) {
  'use cache';
  cacheLife('hours');
  
  const scopedTag = getTenantTag(tenantId, 'invoices');
  cacheTag(scopedTag);
  
  return await db.invoices.findMany({
    where: { tenantId },
  });
}
```

### Server Action Mutation Invalidation with Deterministic Scoping

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Revalidating a generic tag ('invoices') forces an operational cache stampede across every tenant in the system, degrading database performance and invalidating active static payloads system-wide.
```typescript
'use server';

import { revalidateTag } from 'next/cache';
import { db } from '@/lib/db';

// ANTI-PATTERN: Blind global revalidation purging all tenant stores
export async function updateInvoiceStatus(invoiceId: string, status: string) {
  await db.invoices.update({
    where: { id: invoiceId },
    data: { status },
  });

  revalidateTag('invoices'); // Purges cache across the entire application for all tenants
}
```

#### Production Standard (Correct)
> **Standard**: The server action verifies tenant ownership against session context and targets the exact tenant-scoped hash tag for invalidation, eliminating cache stampedes and preventing cross-tenant side effects.
```typescript
'use server';

import { revalidateTag } from 'next/cache';
import { createHash } from 'node:crypto';
import { auth } from '@/lib/auth';
import { db } from '@/lib/db';

function getTenantTag(tenantId: string, entity: string): string {
  const hashedId = createHash('sha256').update(tenantId).digest('hex').slice(0, 16);
  return `tenant:${hashedId}:${entity}`;
}

// PRODUCTION FIX: Session-derived scoped tag invalidation
export async function updateInvoiceStatus(invoiceId: string, status: string) {
  const session = await auth();
  if (!session?.tenantId) {
    throw new Error('Unauthorized');
  }

  await db.invoices.update({
    where: { id: invoiceId, tenantId: session.tenantId },
    data: { status },
  });

  const tenantTag = getTenantTag(session.tenantId, 'invoices');
  revalidateTag(tenantTag);
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Next.js 15 Dynamic I/O & 'use cache' Cryptographic Boundary Standard

Next.js 15 Dynamic I/O & 'use cache' Cryptographic Boundary Standard defines an industrial-grade behavioral standard for frontend engineering. Enforces strict tenant isolation and deterministic cache tagging under Next.js 15 Dynamic I/O architecture. Mandates that all cached execution scopes using the 'use cache' directive bind cryptographic, tenant-scoped cache tags and cacheLife profiles, eliminating multi-tenant data bleed across prerendered edge runtimes and persistent cache stores. 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: Global Unscoped 'use cache' Directives Causing Multi-Tenant Cache Pollution and Cross-Tenant Data Leaks 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 DriftGlobal Unscoped 'use cache' Directives Causing Multi-Tenant Cache Pollution and Cross-Tenant Data LeaksCritical
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 pair the 'use cache' directive with 'cacheTag' calls that include an explicit, verified tenant or user ID prefix.

Engineers MUST ALWAYS pair the 'use cache' directive with 'cacheTag' calls that include an explicit, verified tenant or user ID prefix.

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 ALWAYS declare an explicit 'cacheLife' profile (e.g., 'minutes', 'hours', or custom presets) within every 'use cache' scope to avoid fallback retention hazards.

Engineers MUST ALWAYS declare an explicit 'cacheLife' profile (e.g., 'minutes', 'hours', or custom presets) within every 'use cache' scope to avoid fallback retention hazards.

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 NEVER place the 'use cache' directive in a component or function containing ambient dynamic data access (e.g., headers(), cookies()) without deriving a cryptographic cache-key argument from those primitives.

Engineers MUST NEVER place the 'use cache' directive in a component or function containing ambient dynamic data access (e.g., headers(), cookies()) without deriving a cryptographic cache-key argument from those primitives.

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 isolate cached queries into dedicated, pure data-access layer (DAL) helper functions rather than inlining 'use cache' directly into root RSC layouts or pages.

Code SHOULD isolate cached queries into dedicated, pure data-access layer (DAL) helper functions rather than inlining 'use cache' directly into root RSC layouts or pages.

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 revalidate cached data using 'revalidateTag' targeting the exact deterministic key format

Services MUST revalidate cached data using 'revalidateTag' targeting the exact deterministic key format: `tenant:${tenantId}:${entity}:${entityId}`.

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

Components NEVER render user-private data derived from a shared global cache tag that lacks tenant demarcation.

Components NEVER render user-private data derived from a shared global cache tag that lacks tenant demarcation.

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 Dynamic I/O & 'use cache' Cryptographic Boundary Standard critical for AI coding assistants?

Enforces strict tenant isolation and deterministic cache tagging under Next.js 15 Dynamic I/O architecture. Mandates that all cached execution scopes using the 'use cache' directive bind cryptographic, tenant-scoped cache tags and cacheLife profiles, eliminating multi-tenant data bleed across prerendered edge runtimes and persistent cache stores. 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 (Global Unscoped 'use cache' Directives Causing Multi-Tenant Cache Pollution and Cross-Tenant Data Leaks) 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