Production docs deploys are failing right now — five consecutive production builds OOM-killed. This is the live-outage counterpart to #12683's standing-risk card, and it corrects the attribution in both#12683 and #12698.
Measured (Vercel API + build logs, 2026-08-27)
Vercel's own API on the failed deployment:
errorCode = "out_of_memory"
buildMachine = { purchaseType: "standard", cores: 4, memory: 8192 }
The peak is the Turbopack COMPILE phase, not the prerender
Both failures die between Creating an optimized production build ... and Compiled successfully — with zero output in between:
11:31:03.206 Creating an optimized production build ...
11:42:26.615 ERROR ... exited (137) <- 11m23s of silence
11:43:01.851 Creating an optimized production build ...
11:45:03.086 ERROR ... exited (137) <- 2m of silence
The build never reaches Collecting page data / Generating static pages. So #12683's attribution — "the docs site prerenders 400+ MDX pages", offered as the reason one process holds 7.6 GB — cannot be the mechanism: that phase does not execute. Same for the 403 build-time OG PNGs (app/og/docs/[...slug]/route.tsx) and the 403 markdown routes (app/llms.mdx/docs/[[...slug]]/route.ts) — both are generateStaticParams work in a phase the build dies before.
Two of #12683's negative findings are confirmed by measurement below: --max-old-space-size and experimental.cpus do not bound this peak. experimental.cpus additionally cannot matter here for a structural reason — its static-generation workers have not spawned yet when the kill lands.
Experiment matrix (local cold builds, 403 MDX, peak single-process RSS)
| config | peak | compile | verdict |
|---|
| baseline | 5191 MB | 22.6s | — |
experimental.turbopackSourceMaps: false | 4757 MB | 19.5s | ✅ -434 MB (-8.4%), no downside |
turbopackScopeHoisting: false | 4806 MB | 19.1s | ❌ no effect |
NODE_OPTIONS=--max-old-space-size=2048 | 4734 MB | 18.0s | ❌ no effect (peak is Rust-side, confirming #12683) |
turbopackFileSystemCacheForBuild: true | 4779 MB | 22.2s | ❌ no effect |
+ turbopackMinify: false | 3785 MB | 16.2s | ⚠️ -972 MB more, but rejected |
includeProcessedMarkdown: false | — | — | ❌ build fails (getLLMText / /llms.txt depend on it) |
Why turbopackMinify: false is rejected: client JS goes 5.8 MB -> 16 MB (+176%) — that is real user download weight. Restricting it to the server side (where the memory actually goes: 589 MB of server chunks vs 5.8 MB client) is not available: experimental.serverMinification is consumed only by dist/build/webpack-config.js and is never read on the Turbopack path.
Why sourcemaps are free here
The build emits 260 sourcemap files totalling 348 MB into .next/server. Production serverless functions have no use for them. Next's documented build-time default for turbopackSourceMaps follows productionBrowserSourceMaps (false), but the server-side maps are emitted regardless — setting the flag explicitly is what suppresses them.
Side benefits beyond the memory: 348 MB smaller build output, and compile time drops 22.6s -> 19.5s locally.
Proposed change
// apps/docs/next.config.mjs
experimental: {cpus: 2,turbopackSourceMaps: false,}Honest limitation: local measurement is macOS/arm64; Vercel is Linux/x86_64, and the absolute figures differ substantially (local 4.7 GB vs the 7.6 GB #12683 measured). The ratio is the transferable part, and even it is not a guarantee. Scaling -8.4% onto 7592 MB gives ~6950 MB against an 8192 MB container — roughly 15% headroom. That is thin. It is worth trying first because the cost of being wrong is one build cycle, and #12683's option A (bigger build machine) stays available and unaffected.
Also worth noting: Vercel takes 11 minutes to compile what takes 20s locally. A 4-vs-10 core gap does not explain 30x; the rest is thrashing near the container ceiling. Lowering the peak should cut build time substantially as a side effect.
Correction to #12698
#12698's action 2 ("fix the Ignored Build Step — it skips dependency-only changes") rests on a misreading. The project's actual rule is:
if [ "$VERCEL_ENV" == "production" ]; then exit 1; else exit 0; fi
exit 1 = build, exit 0 = skip. So production always builds and Preview always skips — it is not a path-scoped rule. The Canceled by Ignored Build Step that #12698 read off PR #12684's head was that PR's Preview deployment being skipped, which is the intended behaviour. Pushes to main do trigger production builds; they have simply been OOM-failing. No dashboard change is needed for the ignore step.
Re-check
curl -s https://objectstack.ai/ | grep -o 'data-dpl-id="[^"]*"'
Refs: #12683 (standing-risk card — this adds an option E its set did not contain) · #12698 (ignore-step correction) · #12677 · #12333 · epic #12243.
Production docs deploys are failing right now — five consecutive production builds OOM-killed. This is the live-outage counterpart to #12683's standing-risk card, and it corrects the attribution in both#12683 and #12698.
Measured (Vercel API + build logs, 2026-08-27)
Vercel's own API on the failed deployment:
The peak is the Turbopack COMPILE phase, not the prerender
Both failures die between
Creating an optimized production build ...andCompiled successfully— with zero output in between:The build never reaches
Collecting page data/Generating static pages. So #12683's attribution — "the docs site prerenders 400+ MDX pages", offered as the reason one process holds 7.6 GB — cannot be the mechanism: that phase does not execute. Same for the 403 build-time OG PNGs (app/og/docs/[...slug]/route.tsx) and the 403 markdown routes (app/llms.mdx/docs/[[...slug]]/route.ts) — both aregenerateStaticParamswork in a phase the build dies before.Two of #12683's negative findings are confirmed by measurement below:
--max-old-space-sizeandexperimental.cpusdo not bound this peak.experimental.cpusadditionally cannot matter here for a structural reason — its static-generation workers have not spawned yet when the kill lands.Experiment matrix (local cold builds, 403 MDX, peak single-process RSS)
experimental.turbopackSourceMaps: falseturbopackScopeHoisting: falseNODE_OPTIONS=--max-old-space-size=2048turbopackFileSystemCacheForBuild: trueturbopackMinify: falseincludeProcessedMarkdown: falsegetLLMText//llms.txtdepend on it)Why
turbopackMinify: falseis rejected: client JS goes 5.8 MB -> 16 MB (+176%) — that is real user download weight. Restricting it to the server side (where the memory actually goes: 589 MB of server chunks vs 5.8 MB client) is not available:experimental.serverMinificationis consumed only bydist/build/webpack-config.jsand is never read on the Turbopack path.Why sourcemaps are free here
The build emits 260 sourcemap files totalling 348 MB into
.next/server. Production serverless functions have no use for them. Next's documented build-time default forturbopackSourceMapsfollowsproductionBrowserSourceMaps(false), but the server-side maps are emitted regardless — setting the flag explicitly is what suppresses them.Side benefits beyond the memory: 348 MB smaller build output, and compile time drops 22.6s -> 19.5s locally.
Proposed change
Honest limitation: local measurement is macOS/arm64; Vercel is Linux/x86_64, and the absolute figures differ substantially (local 4.7 GB vs the 7.6 GB #12683 measured). The ratio is the transferable part, and even it is not a guarantee. Scaling -8.4% onto 7592 MB gives ~6950 MB against an 8192 MB container — roughly 15% headroom. That is thin. It is worth trying first because the cost of being wrong is one build cycle, and #12683's option A (bigger build machine) stays available and unaffected.
Also worth noting: Vercel takes 11 minutes to compile what takes 20s locally. A 4-vs-10 core gap does not explain 30x; the rest is thrashing near the container ceiling. Lowering the peak should cut build time substantially as a side effect.
Correction to #12698
#12698's action 2 ("fix the Ignored Build Step — it skips dependency-only changes") rests on a misreading. The project's actual rule is:
exit 1= build,exit 0= skip. So production always builds and Preview always skips — it is not a path-scoped rule. TheCanceled by Ignored Build Stepthat #12698 read off PR #12684's head was that PR's Preview deployment being skipped, which is the intended behaviour. Pushes tomaindo trigger production builds; they have simply been OOM-failing. No dashboard change is needed for the ignore step.Re-check
Refs: #12683 (standing-risk card — this adds an option E its set did not contain) · #12698 (ignore-step correction) · #12677 · #12333 · epic #12243.