Skip to content

fix(tripwire): share aggregates promise across Suspense leaves#34

Merged
n2p5 merged 1 commit intomainfrom
fix/tripwire-page-single-fetch
May 3, 2026
Merged

fix(tripwire): share aggregates promise across Suspense leaves#34
n2p5 merged 1 commit intomainfrom
fix/tripwire-page-single-fetch

Conversation

@n2p5
Copy link
Copy Markdown
Contributor

@n2p5 n2p5 commented May 3, 2026

Summary

The /x/tripwire page had two async server components (HeroLive and StatsLive) that each called getAggregates() independently. React renders them in parallel, so on a cold module cache both fired @vercel/blob's head() simultaneously. Under Bun on Vercel the SDK's internal await apiResponse.json() after its Response goes out of scope can leave one of those parallel calls stuck waiting for EOF — its Suspense boundary then sat on its skeleton forever. A reload warmed the cache and both rendered.

Two changes:

  1. The page kicks off getAggregates() once (without awaiting) and passes the promise to both leaves. One network call, both boundaries reveal together when the data lands. Page shell still streams immediately because the page itself isn't async.
  2. aggregates.ts and stats.ts construct the private blob URL from BLOB_READ_WRITE_TOKEN's storeId instead of calling head() to resolve it. The bearer-token fetch is the path we already know works on Bun-on-Vercel. No SDK call to hang on.

Generated by Claude Code

The /x/tripwire page had two async server components (HeroLive and
StatsLive) that each independently called getAggregates(). React
renders them in parallel, so on a cold module cache both fired
@vercel/blob's head() simultaneously. Under Bun on Vercel, the SDK's
internal `await apiResponse.json()` after its Response goes out of
scope can leave one of those parallel calls stuck waiting for EOF —
its Suspense boundary then sat on its skeleton forever. A reload
warmed the cache and both rendered.

Two changes that converge on the fix:

1. The page kicks off getAggregates() once (without awaiting) and
   passes the promise to both leaves. One network call, both
   boundaries reveal together when the data lands. Page shell still
   streams immediately because the page itself isn't async.

2. aggregates.ts and stats.ts now construct the private blob URL
   from BLOB_READ_WRITE_TOKEN's storeId instead of calling head()
   to resolve it. The bearer-token fetch is the path we already
   know works on Bun-on-Vercel. No SDK call to hang on.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
func-lol Ready Ready Preview, Comment May 3, 2026 7:02pm

Request Review

@n2p5 n2p5 merged commit 6635f04 into main May 3, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants