# Request waterfall flattened; critical path under 3 hops

- **Pattern:** `ab-002036` (`performance-deep-dive.network-waterfall.request-waterfall-optimized`)
- **Severity:** critical
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002036
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002036)

## Why it matters

A request waterfall where API B cannot start until API A completes means your page load time is the sum of all sequential fetch durations, not the maximum. A five-hop waterfall with 200ms fetches adds 1 full second of latency that cannot be improved by any infrastructure optimization — it is a code architecture problem. ISO 25010:2011 time-behaviour formalizes the concern; the user-facing result is a page that appears slow even on fast connections because the CPU is idle while waiting for chained network calls to resolve.

## Severity rationale

Critical because sequential request chains make page load time additive rather than concurrent — each extra hop adds unavoidable latency that cannot be solved by faster servers or better caching.

## Remediation

Replace sequential `await` chains with `Promise.all` for independent fetches. In Next.js Server Components, initiate fetches without `await` at the top of the component to enable parallel execution.

```ts
// app/dashboard/page.tsx — parallel fetches
export default async function DashboardPage() {
  // Start all three fetches simultaneously
  const [user, orders, stats] = await Promise.all([
    fetchUser(),
    fetchOrders(),
    fetchStats(),
  ])
  // ...
}
```

## Detection

- **ID:** `request-waterfall-optimized`
- **Severity:** `critical`
- **What to look for:** Count all sequential API call chains in page components. Enumerate chains where request B depends on request A. Open Chrome DevTools → Network tab. Check the request waterfall. Measure the critical path: count the number of sequential request hops required for the page to become interactive. A typical critical path: (1) HTML → (2) CSS + JS → (3) API data. Ideal is under 3 hops. Look for opportunities to parallelize (fetch multiple APIs at once instead of chained requests).
- **Pass criteria:** The request waterfall shows parallelized requests. Critical path under 3 hops. No request waits for another request before starting.
- **Fail criteria:** Requests are sequential and dependent (A finishes before B starts). Critical path exceeds 3 hops. Request waterfall shows long idle periods.
- **Skip (N/A) when:** Never — network optimization applies to all applications.
- **Report even on pass:** Report the waterfall depth and number of sequential hops: "Critical path: X hops, Y parallel requests."

- **Cross-reference:** For LCP impact of waterfall depth, see the `lcp-optimized` check.
- **Detail on fail:** `"Waterfall shows 5 sequential hops: HTML → CSS → JS → API A → API B → Render. Each request waits for previous to complete"` or `"Long gaps in network activity suggest blocking request dependencies"`
- **Remediation:** Parallelize requests using Promise.all instead of awaiting sequentially. Use prefetch and preconnect links for third-party domains.

  ```ts
  // app/dashboard/page.tsx — parallelize independent fetches
  const [users, products, stats] = await Promise.all([fetchUsers(), fetchProducts(), fetchStats()])
  ```

## External references

- iso-25010 time-behaviour

Taxons: performance

HTML version: https://auditbuffet.com/patterns/ab-002036
