Skip to content

perf(ci): disable the Turbopack persistent build cache (3.2x faster builds) - #6080

Merged
waleedlatif1 merged 2 commits into
stagingfrom
fix/disable-turbopack-build-cache
Jul 30, 2026
Merged

perf(ci): disable the Turbopack persistent build cache (3.2x faster builds)#6080
waleedlatif1 merged 2 commits into
stagingfrom
fix/disable-turbopack-build-cache

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

The Turbopack persistent build cache is a net loss at this app's size. Turning it off cuts the Build App check from 8–20 min to under 3.

Measured, not inferred — a controlled A/B in #6078: three runs on one branch, every commit touching only .github/**, so the Next module graph was byte-identical across all three and only cache state varied.

run flag pre-build disk compile Build App job
C — cache OFF 5.1G (ignored) 113s 2m53s
A — cache ON, cold 4.0K 162s 3m54s
B — cache ON, warm 5.1G 360s 8m18s

A warm cache made the identical build 3.2× slower than no cache.

Why it degrades: the cache grows, it doesn't converge

Run B started from 5.1 GB and committed 12 GB — on a tree where nothing changed. That's the mechanism behind the progressive slowdown on longer-lived disks (observed up to 11.7 min): every run adds to what the next must read and revalidate, so a disk gets worse the more it's used. This also corrects an earlier theory of mine that cache mismatch was the variable — accumulated size matters more.

Validity controls

  • Flag manipulation confirmed in the logs — cache-on runs print ✓ turbopackFileSystemCacheForBuild; the cache-off run omits it entirely.
  • Every run used turbo --force. Without it, a .github-only commit leaves Turbo's task inputs unchanged, so Turbo replays a cached log and reprints a stale compile time — fabricating the number being measured. Five such phantom runs had to be discarded from the observational data first.
  • No cancelled siblings. cancel-in-progress means an early push cancels a run, and a cancelled run still commits its partial cache. Each run here reached completed before the next push. This mattered: an earlier conclusion of mine ("a brand-new sticky key is not cold") was wrong precisely because the "first" run had a cancelled sibling that had already written 5.1 GB.

What this removes, and what it doesn't

#5869 enabled the cache on locally-measured numbers (105s cold → 22s warm) that never reproduced in CI and are inverted here. #6072 then branch-scoped the disk to stop PRs restoring each other's caches — that fixed a real problem, but with the cache off the disk serves nothing, so the mount, the size reporting, and the env gate go with it.

turbopackFileSystemCacheForBuild: false is pinned explicitly rather than left to the Next default, because upstream already flips that default to true in canary/preview builds (#94616) — relying on the default would let a version bump silently re-enable a config we measured as harmful.

ci-cache-cleanup.yml is kept, re-scoped. PRs opened while the per-branch key was live still hold 5–12 GB volumes and nothing else reclaims them; deleting the workflow now would orphan that storage. It's a no-op for new PRs and can be removed once drained.

Caveat

n=1 per cell. The 3.2× effect size and its agreement with ~15 prior observations make this convincing, but it is three runs, not a distribution. The change is a one-line revert if staging disagrees.

Cross-commit restore is separately undocumented-as-supported (#87283 reports stale HTML from a cache built at another commit), so turning it off also removes a correctness risk.

Type of Change

  • Performance
  • Improvement

Testing

tsc --noEmit exit 0, biome clean, actionlint clean on both changed workflows. No dangling references to NEXT_TURBOPACK_BUILD_CACHE or the nextjs-cache key remain. This PR's own Build App run is the confirmation — expect ~2–3 min.

It is a net loss at this app's size. A controlled A/B on one branch (#6078),
three runs with a byte-identical module graph so only cache state varied:

  cache OFF        113s compile, 2m53s job
  cache ON, cold   162s compile, 3m54s job
  cache ON, warm   360s compile, 8m18s job

The cache made the same build 3.2x slower. It also grew 5.1 GB -> 12 GB
across two runs of an unchanged tree, which explains the progressive
degradation seen on longer-lived disks (up to 11.7 min): the more a disk is
written, the more the next run must read and revalidate. Flag manipulation
is visible in the logs — the cache-on runs print
`✓ turbopackFileSystemCacheForBuild`, the cache-off run omits it — and every
run used `turbo --force` so none is a replayed log.

#5869 enabled this on locally-measured numbers (105s cold -> 22s warm) that
never reproduced in CI and are inverted here. #6072 then branch-scoped the
disk to stop PRs restoring each other's caches; that fixed a real problem,
but with the cache off the disk is unnecessary, so the mount, the pre/post
size reporting, and the env gate all go with it.

Pins `turbopackFileSystemCacheForBuild: false` explicitly rather than relying
on the Next default: upstream already flips that default to true in
canary/preview builds (vercel/next.js#94616), so leaning on the default would
let a version bump silently re-enable this.

Keeps ci-cache-cleanup.yml, re-scoped to draining the 5-12 GB volumes that
PRs opened while the per-branch key was live still hold — nothing else
reclaims them. It is a no-op for new PRs and can be deleted once drained.

Caveat: n=1 per cell. The 3.2x effect size and agreement with ~15 prior
observations make it convincing, but this is three runs, not a distribution.
@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview Jul 30, 2026 2:02am

Request Review

@cursor

cursor Bot commented Jul 30, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
CI and Next build-cache config only; no app runtime, auth, or data paths. Reversible if staging build times disagree.

Overview
Disables Turbopack’s persistent build cache after A/B showed it slowed identical CI compiles (~113s off vs ~360s warm) and bloated disk (5→12 GB). turbopackFileSystemCacheForBuild is hard-coded to false in next.config.ts so a Next upgrade can’t silently turn it back on.

CI build job drops the .next/cache sticky disk mount, NEXT_TURBOPACK_BUILD_CACHE, and pre/post cache size reporting; comments document why the mount is gone.

ci-cache-cleanup.yml stays only to delete legacy per-PR sticky disks from when the cache was mounted; it’s documented as temporary drain work, not tied to the removed mount step.

Reviewed by Cursor Bugbot for commit e539058. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Disables Turbopack’s persistent build cache and drops the CI .next/cache sticky-disk mount after measured 3.2× slower warm builds.

  • Pins turbopackFileSystemCacheForBuild: false in apps/sim/next.config.ts (no longer gated by NEXT_TURBOPACK_BUILD_CACHE).
  • Removes the Next.js cache mount and pre/post size reporting from test-build.yml.
  • Keeps ci-cache-cleanup.yml as a legacy drain for per-branch disks from older PRs, with updated comments.

Confidence Score: 5/5

This PR appears safe to merge; no blocking failures remain.

Prior stale cleanup-comment feedback is addressed on HEAD, and the cache-off plus mount-removal path leaves no remaining blocking failure.

Important Files Changed

Filename Overview
apps/sim/next.config.ts Hard-disables turbopackFileSystemCacheForBuild so CI/prod cannot re-enable the cache via env or Next default flips.
.github/workflows/test-build.yml Drops Next.js sticky-disk mount, cache size reports, and NEXT_TURBOPACK_BUILD_CACHE from the Build App job.
.github/workflows/ci-cache-cleanup.yml Documents legacy-only drain of old nextjs-cache disks; delete-key pattern unchanged for backlog reclamation.

Reviews (2): Last reviewed commit: "docs(ci): correct the cleanup key commen..." | Re-trigger Greptile

Greptile P2: the delete step still claimed its key must stay byte-identical
to the Mount Next.js build cache step in test-build.yml, but this PR removes
that mount. It is now a hard-coded legacy drain key that mirrors nothing.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

Fixed the P2 in ci-cache-cleanup.yml (e539058). You were right — the step comment claimed its key had to stay byte-identical to the Mount Next.js build cache step that this PR removes, so it referenced something that no longer exists.

It now states what the key actually is: a hard-coded legacy drain key that mirrors nothing, with an explicit warning not to retarget or delete it while pre-removal PRs are still open (their 5–12 GB disks would otherwise never be reclaimed).

Flagging it as an outside-diff comment rather than a thread was the right call given the line wasn't in the diff — but it also meant reviewThreads reported zero unresolved, so the 4/5 score was the only signal it existed.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit e539058. Configure here.

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.

1 participant