Skip to content

perf(api): stream mapping eviction to fix OOM from whole-index loading#828

Open
mohammed90 wants to merge 1 commit into
darkweak:masterfrom
mohammed90:perf/stream-mapping-eviction
Open

perf(api): stream mapping eviction to fix OOM from whole-index loading#828
mohammed90 wants to merge 1 commit into
darkweak:masterfrom
mohammed90:perf/stream-mapping-eviction

Conversation

@mohammed90

Copy link
Copy Markdown
Contributor

Problem

Production Caddy instances OOM after deploying the latest build. Heap profiling
shows EvictMappingMapKeys holding 325 MB + 43 MB live at snapshot
time — the eviction job loads the entire Redis mapping index into memory every
interval (default: 1 minute).

Changes

⚠️ Dependency note

The previous pin (core v0.0.20-0.20260314133624-4df176921261) pointed at the
perf/core/reduce-overhead branch, which returns pooled lz4/bufio readers to
their pools before http.Response.Body is consumed — the same use-after-put
race class fixed in storages v0.0.19. The bump moves off that branch; do not
re-pin to it.

Testing

  • go test ./pkg/api/... ./pkg/middleware/... — green.
  • Storer-level batching behavior covered by tests in the storages PR.

Expected impact

  • Eviction memory: O(index size) → O(batch) per run.
  • Steady-state allocation rate drops sharply (64 KB lz4 blocks vs 4 MB).
  • Redis mapping index becomes self-pruning via TTLs.

Rollout notes

  • Recommend setting GOMEMLIMIT (~80% of container limit) and reviewing
    mapping_eviction_interval and max_cacheable_body_bytes.
  • Surrogate-key storage growth is a known remaining issue, addressed separately.

EvictMapping fetched the entire mapping index via MapKeys before
processing it. With the go-redis storage this materialized hundreds of
MB per run (325 MB live in a production heap profile) on every eviction
interval, which is the primary driver of the OOM crashes.

Process mappings one entry at a time through the storer's
MappingWalker when available, falling back to MapKeys for storers that
don't implement it. Peak memory for an eviction run drops from
O(index size) to O(batch).

Temporarily replace darkweak/storages/core with the fork commit that
provides MappingWalker, bounded mapping key TTLs and 64 KB lz4 blocks,
so canary builds can validate the fix. The replace also moves off the
perf/core/reduce-overhead pseudo-version, which pools lz4/bufio readers
that escape through http.Response.Body and can serve truncated
responses under concurrency. Swap the replace for a tagged upstream
release once darkweak/storages merges the changes.
@netlify

netlify Bot commented Jul 7, 2026

Copy link
Copy Markdown

Deploy Preview for teal-sprinkles-4c7f14 canceled.

Name Link
🔨 Latest commit bac29ea
🔍 Latest deploy log https://app.netlify.com/projects/teal-sprinkles-4c7f14/deploys/6a4d8a17ccf1fa0008e2c5ab

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