From 4efb94cd8898971c186e653b8e9195cef07bce8b Mon Sep 17 00:00:00 2001 From: Darius Cepulis Date: Thu, 26 Feb 2026 11:19:40 -0600 Subject: [PATCH] fix(site): disable Netlify edge functions in dev to prevent Deno OOM (#620) --- internal/design/site/netlify-dev-deno-oom.md | 62 ++++++++++++++++++++ site/package.json | 2 +- 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 internal/design/site/netlify-dev-deno-oom.md diff --git a/internal/design/site/netlify-dev-deno-oom.md b/internal/design/site/netlify-dev-deno-oom.md new file mode 100644 index 00000000..9bf8e0ad --- /dev/null +++ b/internal/design/site/netlify-dev-deno-oom.md @@ -0,0 +1,62 @@ +--- +status: decided +date: 2026-02-26 +--- + +# Disable Netlify Edge Functions in Dev + +## Decision + +Set `NETLIFY_DEV=1` before `astro dev` to disable `@netlify/vite-plugin` entirely, preventing Deno from spawning during local development. + +```jsonc +// site/package.json +"dev": "NETLIFY_DEV=1 astro dev" +``` + +## Context + +Running `pnpm dev` intermittently crashes with a fatal Deno OOM error: + +``` +Fatal process out of memory: JSDispatchTable::AllocateAndInitializeEntry +``` + +The crash originates in V8 isolate initialization — before any of our code runs. Netlify's dev server spawns Deno web workers for edge functions, and a known Deno/V8 bug ([denoland/deno_core#1091](https://github.com/denoland/deno_core/issues/1091)) causes OOM during `JSDispatchTable` allocation. + +Our only edge function is `site/netlify/edge-functions/markdown-negotiation.ts`, which serves `.md` files for requests with `Accept: text/markdown` on `/blog/*` and `/docs/*` paths (for LLM consumption). + +## Alternatives Considered + +- **Bump `@netlify/vite-plugin`** — Upgraded 2.8.0 → 2.10.2. OOM still reproduces; the root cause is in Deno's V8, not Netlify's tooling. + +- **Move edge function to Astro middleware** — Prerendered pages are served as static files from the CDN. Astro middleware only runs for SSR pages, so it never intercepts the static `/blog/*` and `/docs/*` routes. + +- **Move to a serverless function** — Serverless functions don't support the `header` config property. Our edge function relies on `header: { accept: 'text/markdown' }` to scope to markdown-requesting clients. Without it, the function would run on every `/blog/*` and `/docs/*` request. + +- **`DENO_V8_FLAGS=--max-old-space-size=8192`** — Targets the JS heap, not V8 internal structures like `JSDispatchTable`. Could make things worse by increasing per-isolate memory reservation. + +- **Early-return in dev (`context.deploy.context === 'dev'`)** — The OOM occurs during Deno isolate initialization, before any handler code runs. Early-return can't prevent it. + +- **`middleware: false` on `@netlify/vite-plugin`** — Only skips registering the Vite request middleware. `NetlifyDev` is still created and `start()` still spawns Deno. + +- **`devFeatures: false` on `@astrojs/netlify`** — Only controls `images` and `environmentVariables`. The adapter never passes `edgeFunctions` to `@netlify/vite-plugin`, so edge functions always default to enabled. + +- **Pass `edgeFunctions: { enabled: false }` to `@netlify/vite-plugin`** — The correct lever (`NetlifyDev` skips Deno when `edgeFunctions.enabled` is `false`), but `@astrojs/netlify` doesn't expose this option. Would require patching adapter internals — fragile and breaks on updates. + +## Rationale + +`NETLIFY_DEV=1` is an official escape hatch in `@netlify/vite-plugin`. When set, the plugin's factory returns `[]` — no `NetlifyDev` instance, no Deno, no OOM. + +**What we lose in dev:** + +| Feature | Impact | +|---|---| +| Netlify Image CDN | Falls back to Astro's built-in image service (still works) | +| Redirect emulation | Only affects legacy routes (`/city`, `/fantasy`, etc.) | +| Edge function emulation | The markdown negotiation function doesn't matter in dev | +| Blob storage | Not used in typical dev workflow | + +None of these are essential for local development. The Astro adapter still handles SSR, sessions, and builds normally. + +**Tracking:** [#588](https://github.com/videojs/v10/issues/588) diff --git a/site/package.json b/site/package.json index 08ec9e46..09d6a20e 100644 --- a/site/package.json +++ b/site/package.json @@ -5,7 +5,7 @@ "scripts": { "api-docs": "tsx scripts/api-docs-builder/src/index.ts", "predev": "pnpm api-docs", - "dev": "astro dev", + "dev": "NETLIFY_DEV=1 astro dev", "prebuild": "pnpm api-docs", "build": "astro build", "astro": "astro",