Skip to content

fix(ci): Batch Algolia record uploads to stop heap OOM on master - #18846

Merged
sergical merged 2 commits into
masterfrom
sergical/fix/algolia-index-oom-batched-uploads
Jul 27, 2026
Merged

fix(ci): Batch Algolia record uploads to stop heap OOM on master#18846
sergical merged 2 commits into
masterfrom
sergical/fix/algolia-index-oom-batched-uploads

Conversation

@sergical

@sergical sergical commented Jul 27, 2026

Copy link
Copy Markdown
Member

DESCRIBE YOUR PR

The user-docs Algolia index has not been updated since 2026-05-15. Every master push touching docs/**, includes/**, or platform-includes/** fails the Build index for user docs step with exit 134 (V8 heap limit), ~40s into record generation and after a ~10 minute build — ~70 consecutive runs, ~13 min of CI burned each. develop-docs pushes still pass because that corpus is 306 pages vs 10,219.

Root cause

scripts/algolia.ts generated every record for all ~10.2k pages into a single array before uploading — ~244k records — which exceeds Node's default ~4GB old-space limit.

Corroborated in Sentry (sentry/docs, metrics dataset, 90d)

Metric docs_type:user-docs docs_type:developer-docs
algolia.pages_total 9,882 — 2026-05-12, nothing since 305–306, through 2026-07-10
algolia.records_total 237,987 — 2026-05-12 10,199 → 10,356, through 2026-07-21
algolia.cache_misses 9,880 / 9,881

User-docs telemetry flatlines on 2026-05-13 while develop-docs keeps reporting weekly — the same
boundary the CI logs show, arrived at independently. The gauges only emit if the process reaches
Sentry.flush(), and the heap OOM is a V8 SIGABRT, so there is also no error event: zero issues in
the docs project mention algolia in 90d. A 10-week outage left no signal except red checks on
master.

Changes

  • Generate and upload in batches of 500 pages, so each batch's records are reclaimed before the next is built. Peak heap is now flat as the corpus grows.
  • Read existing objectIDs once up front (record objectIDs are auto-generated per run, so the pre-existing set must be captured before any upload).
  • Move stale-cache-file cleanup after the batch loop — inside it, it would delete cache files for pages in later batches.
  • Add ALGOLIA_DRY_RUN_PAGE_LIMIT so the full corpus can be load-tested without touching the index.
  • Add heap headroom scoped to the indexing script only. Setting NODE_OPTIONS job-wide (fix(ci): resolve OOM in Algolia index workflow #17283) let next build outgrow the runner and got the runner OOM-killed, which fix(ci): remove NODE_OPTIONS causing OOM in Algolia workflow #17711 then had to undo.

Verification

Full 10,099-page corpus, cold cache:

Heap cap Result Peak RSS
Before 4096 MB FATAL ERROR: Reached heap limit at 4,095 MB — same signature as CI 2.05 GB
After 1024 MB 244,085 records / 10,099 pages in 37s 1.33 GB

The upload path needs the Algolia keys, so batched saveObjects is only exercised on merge. Note it widens a pre-existing window: stale records are deleted only after all batches upload, so a mid-run failure leaves old + partial-new records in the index until the next green run (previously a failure wrote nothing).

Follow-ups not in this PR

  • The content-hash cache is still effectively a no-op (2 hits / ~9,940 misses). Either fix it (hash MDX source, rolling actions/cache key, namespace the dir per docs type) or remove it.
  • No alerting on index staleness — this ran red for 10 weeks unnoticed. The alert should read the
    Algolia index's own last-updated timestamp rather than these gauges, which the failure itself
    suppresses. (Also unresolved: the aggregate query reports 48 algolia.pages_total rows over 90d
    while the samples view returns 6, so row counts here aren't yet trustworthy.)

IS YOUR CHANGE URGENT?

Help us prioritize incoming PRs by letting us know when the change needs to go live.

  • Urgent deadline (GA date, etc.): search index is 10 weeks stale
  • Other deadline:
  • None: Not urgent, can wait up to 1 week+

SLA

  • Teamwork makes the dream work, so please add a reviewer to your PRs.
  • Please give the docs team up to 1 week to review your PR unless you've added an urgent due date to it.
    Thanks in advance for your help!

PRE-MERGE CHECKLIST

Make sure you've checked the following before merging your changes:

  • Checked Vercel preview for correctness, including links
  • PR was reviewed and approved by any necessary SMEs (subject matter experts)
  • PR was reviewed and approved by a member of the Sentry docs team

The user-docs Algolia index has not updated since 2026-05-15. Every master
push touching docs/, includes/, or platform-includes/ fails with exit 134
(V8 heap limit) roughly 40s into record generation, after a 10-minute build.

The script generated every record for all ~10.2k pages into one array before
uploading: ~244k records, which exceeds Node's default ~4GB old-space limit.
This passed under Bun (no comparable heap cap) and started failing when the
script moved to tsx in #17772; the module-resolution error fixed in #18265
masked it for three weeks. The content-hash cache added in #17722 was never
protection here: it hashes built HTML, so it hits on 2 of ~9940 pages.

Generate and upload in batches of 500 pages so each batch's records are
reclaimed before the next is built, keeping peak heap flat as the corpus
grows. Existing objectIDs are read once up front, since record objectIDs are
auto-generated per run. Stale-cache-file cleanup moves after the batch loop,
where it can still see every page that was used.

Also add heap headroom scoped to the indexing script only. Setting
NODE_OPTIONS job-wide (#17283) let next build outgrow the runner and got the
whole runner OOM-killed, which #17711 then had to undo.

Verified on the full 10,099-page corpus with a cold cache: the previous code
dies at the 4GB cap, this generates all 244,085 records under a 1GB cap with
1.33GB peak RSS.

Co-Authored-By: Claude <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
develop-docs Ready Ready Preview Jul 27, 2026 7:33pm
sentry-docs Ready Ready Preview Jul 27, 2026 7:33pm

Request Review

Comment thread scripts/algolia.ts Outdated
`Number(process.env.ALGOLIA_DRY_RUN_PAGE_LIMIT ?? 200)` applied the nullish
default to the raw env var, not to the parse result, so an empty or
non-numeric override became 0 or NaN. Both slice to an empty page list, which
would report a green dry run that had checked nothing.

Parse explicitly and fall back to the default unless the override is a
positive integer.

Co-Authored-By: Claude <noreply@anthropic.com>
@sergical
sergical merged commit 73a7318 into master Jul 27, 2026
25 checks passed
@sergical
sergical deleted the sergical/fix/algolia-index-oom-batched-uploads branch July 27, 2026 22:43
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