Raxx · internal docs

internal · gated

RCA — ci-monitoring box memory pressure root-caused to uncapped devpi-server; fleet hardened

Incident ID: 2026-08-13-ci-monitoring-devpi-memory-pressure Date: 2026-08-13 Severity: SEV-3 (non-blocking degradation — monitoring/alerting infrastructure at risk, no customer-facing or CI-functional outage occurred) Duration: MemoryPressureHigh{instance="ci-monitoring"} active continuously 2026-08-07 09:37 UTC → 2026-08-13 12:41 UTC (~6 days) before this response; hardening applied and verified within ~25 minutes of a single maintenance window Blast radius: ci-monitoring EC2 (Prometheus/Alertmanager/Grafana/blackbox-exporter/node-exporter/registry-mirror/devpi-server) — the CI observability and build-cache stack. No impact to the Woodpecker CI server, pipelines, or any customer-facing surface. Author: sre-agent

Summary

Operator escalation on unactioned issue #4435 ("ci-monitoring box memory pressure ~95% used") triggered a full fleet review. Root cause: devpi-server (the PyPI caching mirror added 2026-08-05 as part of the CI build-cache cost-reduction pass, #4393) runs directly on the host as a systemd service with no memory ceiling, and its in-process RSS grew unboundedly to 1.17 GB (63% of the box's 2 GB total) over its first ~8 days of uptime — dwarfing the combined ~190 MB footprint of the box's six Docker containers. No swap existed as a backstop. Applied non-disruptive hardening (per-container mem_limit, a MemoryHigh/MemoryMax systemd cap on devpi-server, a 2 GB swap file, and journald caps) inside a single CI-scoped Alertmanager maintenance silence; the devpi-server restart this required reset its RSS from 1.17 GB to ~540 MB and the box's memory usage from 93.9% to 57.5%. The Woodpecker CI server (i-0563f92028b656333) was investigated in parallel and found healthy (23% memory used, no pressure) — it received only non-disruptive hygiene (swap, journald caps) applied live; a proposed IaC change to add container mem_limits there was reverted after it broke the server's tight 12 KB raw user_data byte budget (see "What didn't go well"). MooseQuest-LLC/project-avenue was confirmed to share this same Woodpecker instance, agent fleet, and — critically — the same global devpi/registry-mirror caches (the pip-index wiring is server-level, not per-repo), so Avenue's own package/image pulls do proportionally contribute to the cache growth that drove this pressure; no evidence of Avenue-caused OOM kills, wedge events, or queue contention was found in the same window.

Timeline (all times UTC)

Impact

What went well

What didn't go well

Root cause analysis

Detection

Resolution

Action items

# Action Owner Due Issue
1 Extend or scope a variant of #4434 ("critical alert firing continuously with no maintenance silence") to also catch a warning-severity CI alert active continuously for N+ days — the gap this incident actually fell through was escalation of an unactioned alert, not detection sre-agent 2026-08-27 #4434 (extend)
2 Fold MemoryHigh/MemoryMax (or an equivalent resource-limit review) into the standard checklist for adding any new systemd-managed (non-Docker) service to ci-monitoring, mirroring what already exists for Docker mem_limit — the node_exporter precedent that justified building devpi-server as a systemd service should have also carried this forward sre-agent 2026-09-03 filed, see PR
3 Implement gzip-compressed user_data for the Woodpecker CI server (infra/ci/server.tf + user_data_server.sh.tpl), per the standing #4453 ruling — this incident is the second time (after #4426/#4432) a reasonable, small addition to that template was blocked by the 12,100-byte guard; the WP-server-side swap/journald/mem_limit hardening applied here live is NOT yet in IaC and needs this follow-up to land safely sre-agent 2026-09-10 filed, see PR
4 Avenue-owner follow-up (handoff, not a TradeMasterAPI action item): pipeline #187 on MooseQuest-LLC/project-avenue ran for 4.4 hours (2026-08-06 13:28–17:55 UTC) before being killed — anomalously long relative to the rest of that repo's pipeline history (typically 1–25 min); worth investigating on the Avenue side. Separately, Avenue's pipelines share this fleet's global devpi/registry-mirror caches with no per-repo isolation or usage accounting — any future cache-capacity work here should account for both repos' load, not just TradeMasterAPI's operator (Avenue owner) n/a handoff note, not a GH issue in this repo
5 Operator resize decision (Phase 3 proposal, not executed here): now that the acute pressure is resolved via tuning, evaluate whether t4g.small → t4g.medium (+~$13/mo) is still warranted for future headroom, or whether the applied caps are sufficient — see proposal in the PR description operator n/a #4435 (comment posted, left open for operator decision)

References