LearnNewsExamplesServices
Frontmatter
id12746
titleBound the miniSummary backfill loop (rate-limit + retry backoff)
stateClosed
labels
bugaiarchitectureperformancemodel-experience
assigneesneo-opus-grace
createdAtJun 8, 2026, 10:12 AM
updatedAtJun 9, 2026, 10:25 AM
githubUrlhttps://github.com/neomjs/neo/issues/12746
authorneo-opus-grace
commentsCount2
parentIssue12740
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 9, 2026, 10:25 AM

Bound the miniSummary backfill loop (rate-limit + retry backoff)

Closed v13.0.0/archive-v13-0-0-chunk-17 bugaiarchitectureperformancemodel-experience
neo-opus-grace
neo-opus-grace commented on Jun 8, 2026, 10:12 AM

Context

The 2026-06-08 €50 Gemini cost incident: the orchestrator's mini-summary backfill looped back-to-back (50-row batches from 06:43:24Z, repeating ~every 2 min through the window) with a 429-retry storm (orchestrator.log: 165 retry/429 mentions). #12742 fixes the provider default (→ local), but the loop itself is unbounded — a defense-in-depth gap: a local model can also be saturated, and an unbounded back-to-back drain + insufficient retry backoff is a runaway shape regardless of provider.

The Problem

The backfill drains pending mini-summaries in immediate back-to-back batches (no inter-batch pacing) and, per the incident, generated a 429-retry storm. Even post-#12742 (local provider) an unbounded drain can saturate the local endpoint / spike CPU.

The Architectural Reality

  • ai/daemons/orchestrator/services/ProcessSupervisorService.mjs + ai/daemons/orchestrator/taskDefinitions.mjs (memory-summary-backfill task) schedule/spawn the backfill.
  • ai/scripts/lifecycle/backfill-memory-summaries.mjs — the batch loop (50 pending/batch).
  • orchestrator.log: Starting memory miniSummary backfill (pending-memory-minisummary:50) → completes → immediately restarts (back-to-back, 06:43→07:42Z).
  • The provider-call retry path (verify backoff behavior; the 429-storm suggests insufficient backoff).

The Fix

  • Inter-batch rate-limit — a minimum interval between backfill batches (no back-to-back unbounded loop), or a per-sweep cap with the remainder deferred to the next scheduled sweep.
  • Bounded, backed-off retries — 429-aware exponential backoff + a max-retry ceiling (no tight retry storm).
  • Defense-in-depth: applies regardless of provider (local or remote).

Decision Record impact

aligned-with ADR 0019 (reads config at use site; no mutation). Orchestrator-scheduling change.

Acceptance Criteria

  • Backfill does not fire back-to-back batches unboundedly — a minimum inter-batch interval (or per-sweep cap) is enforced.
  • Provider-call retries use bounded exponential backoff (429-aware) with a max-retry ceiling; no tight retry loop.
  • A test verifies the pacing + backoff (no live API).

Out of Scope

  • Provider default (local) — #12742. Test isolation — sibling leaf. KB-ask / key hygiene — gpt's #12741 / #12744.

Avoided Traps

  • Relying solely on #12742 (local provider) — the unbounded loop is a runaway shape regardless of provider (local saturation / CPU spike).
  • Relying solely on the per-call timeout/abort (#12712 / #12722) — that caps a single hung call, not the back-to-back loop or the retry storm.

Related

  • #12740 (epic parent). #12742 (provider-default sibling). #12713 (origin). #12712 / #12722 (per-call symptom guards). #12743 (gpt — spend/volume reconciliation).
  • €50 Gemini cost incident, 2026-06-08.

Live latest-open sweep: checked latest 10 open + targeted search at 2026-06-08T08:10Z; no backfill-safety dup; siblings under epic #12740.

Origin Session ID: 1cf2ad9f-28af-4242-9069-fd14c04e1b62 Retrieval Hint: query_raw_memories("miniSummary backfill back-to-back loop rate-limit 429 retry storm")

Authored by Claude Opus 4.8 (Claude Code), @neo-opus-grace.

tobiu referenced in commit d58bb0e - "fix(memory-core): bound miniSummary backfill run under the supervisor watchdog (#12746) (#12802) on Jun 9, 2026, 10:25 AM
tobiu closed this issue on Jun 9, 2026, 10:25 AM