Capacity and throughput
Real throughput and concurrency numbers for AMS's iterate-loop and the review-gate's PR-processing queue, so an operator can plan for load instead of guessing.
Real throughput and concurrency numbers for AMS's iterate-loop and the review-gate's PR-processing queue — the counterpart to Resource sizing (CPU/RAM/disk), scoped strictly to throughput/concurrency and where each number comes from.
AMS: iterate-loop orchestration throughput
From the committed load-test harness (packages/loopover-engine/docs/iterate-loop-load-test.md,
built for #4913/#5224), measuring runIterateLoop's own orchestration overhead under concurrent,
multi-tenant-like load with a 15ms simulated per-iteration driver latency:
- Concurrency 1
- 63 attempts/sec
- Concurrency 8
- 422 attempts/sec
- Concurrency 32
- 982 attempts/sec
- Concurrency 128
- 1,577 attempts/sec
Absolute numbers are host-dependent — treat these as a rough sense of scale and of how throughput scales with concurrency, not a hard target. Reproduce them on your own hardware with:
npm run loadtest:iterate-loopbashReview-gate: PR-processing concurrency caps
Fixed, hardcoded caps from src/settings/agent-sweep.ts, sized against a single GitHub App
installation's shared ~5,000-request/hour REST rate-limit bucket (each PR touched costs roughly 9
REST GETs):
- SWEEP_MAX_PRS = 3
- The recurring sweep's per-tick cap — sized for a sweep that re-runs every ~2 minutes, so a low steady-state budget compounds safely across ticks.
- ISSUE_WAKE_MAX_PRS = 25
- One-shot budget for an issue-linked wake event — a rarer trigger than a merge, so a larger one-time budget doesn't risk compounding across repeated events in one rate-limit window.
- MERGE_WAKE_MAX_PRS = 15
- One-shot budget for a merge-triggered wake — sized lower than the issue-wake budget because merges are a far more common trigger; a repeated-merge burst inside one rate-limit window must not compound the way the rarer issue-wake trigger safely can.
Review-gate: Cloudflare Queue consumer bounds
From wrangler.jsonc's loopover-jobs queue consumer — Cloudflare Queues consumer-binding
attributes, read at wrangler deploy time (not runtime-configurable via env.SOMETHING):
- max_batch_size = 5
- The most jobs one batch can bundle at once — bounds how many heavy sweep/backfill jobs land in a single delivery.
- max_concurrency = 8
- Global consumer fan-out for multi-tenant volume (#4892) — aligned with the #4913 load-test concurrency=8 band. Per-installation admission (default limit 2) still caps how many background GitHub-budget jobs one tenant may run at once, so raising the global bound cannot let a single installation monopolize every worker slot.
max_batch_size × max_concurrency (5 × 8 = 40) bounds Worker in-flight work. Rate-limit safety across
tenants comes from two already-shipped layers: each GitHub App installation has its own REST budget,
and installation-concurrency-admission.ts (#2970) caps per-install background GitHub fetches. Further
re-tuning still benefits from live audit_events / dashboard volume data when available — these defaults
are the architecture-justified baseline after the #4903–#4913 scaling work, not a production-volume fit.
Takeaways:
- Iterate-loop's own orchestration overhead scales roughly linearly with concurrency — the bottleneck at real scale is each attempt's actual coding-agent driver latency, not the loop's scheduling/bookkeeping around it.
- The review-gate's PR-processing caps are deliberately asymmetric across trigger type
(
SWEEP_MAX_PRS<MERGE_WAKE_MAX_PRS<ISSUE_WAKE_MAX_PRS) because each trigger recurs at a different rate — a budget sized for a rare trigger would compound dangerously if applied to a frequent one. - Every number above was measured or verified directly against the source it's read from (the committed load-test harness, or the literal constant/config value) — none are estimates.
See Resource sizing for CPU/RAM/disk numbers, and the AMS Cloud Readiness milestone for the per-tenant scheduling and queue-fairness design work these numbers feed into.