fix(build): cut esbuild peak memory to avoid builder oom#60115
Merged
Conversation
Contributor
|
🎭 Playwright didn't run on this PR — your changes touch code that could affect E2E behavior, but Playwright is opt-in via label now to keep CI cost down. Add the Most PRs don't need this. Real regressions still get caught on master and fix-forward. |
Contributor
|
Size Change: 0 B Total Size: 80.1 MB ℹ️ View Unchanged
|
Contributor
|
Reviews (1): Last reviewed commit: "Merge branch 'master' into worktree-cap-..." | Re-trigger Greptile |
gantoine
approved these changes
May 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Docker
[frontend-build]step intermittently OOM-kills the Depot builder (surfaces in CI askeepalive ping failed to receive ACK within timeout). The killed process is esbuild's Go service: the frontend build runs 8 esbuild builds via an unboundedPromise.all, and the two heavy full-app bundles (PostHog App,Exporter) keep their build graphs resident at once. Contexts are never disposed until the process exits, so every graph piles up — the summed peak hits the builder's memory ceiling.Changes
NODE_OPTIONS=--max-old-space-sizecap — esbuild's memory is in its Go process, outside V8's heap, so it can't help.How did you test this code?
Agent-authored (Claude Code), automated only — no manual UI testing.
Real-bundle A/B, same machine, only the two changed files toggled, sampling esbuild process RSS (3 reps each): 11006 MB → 7230 MB peak, −34%, ranges fully separated, ~+2s build time. A synthetic harness isolating the mechanism showed serialize-without-dispose is unreliable — dispose-on-complete is the load-bearing part. This PR's Container Images run built the frontend cold and succeeded with zero OOM.
Publish to changelog?
no
Docs update
No docs change needed.
🤖 Agent context
Promise.all, 2 heavy + 6 light, no dispose until exit).NODE_OPTIONSheap cap (wrong process — esbuild is Go, not V8) and mutex-only (without dispose, peak barely moves since the first graph stays resident and Go keeps the high-water mark). Chose serialize + dispose-on-complete.try/finally(benign — the process exits on build failure); the Toolbar bundle isn't markedheavy(empirically fine, worth watching if it grows).