On crud-4096, vanilla-epoll does 0.31M rps and emits 69,764 5xx while ioxide (C#) does 0.80M against the same Postgres — so the DB has headroom vanilla isn't using. The 503s are the async pool shedding when every pooled connection is at max_inflight (frameworks/vanilla-epoll/main.v:288-294, acquire_pipelined shed path ~:394); the shed is "honest", but the low rps + high shed rate suggests the per-worker pool size / pipelining depth (max_inflight) / worker-count split (main.v ~:1300) is under-provisioned for this mix (75% GET-cached / 15% PUT / 5% list / 5% create).
Investigate (medium confidence — the audit's verify pass was cut short):
- per-worker pool connections vs
max_inflight vs worker count, and the per_worker budget split;
- whether raising pipelining depth or pool size closes the gap to ioxide without saturating PG;
- the read-path shed-to-empty-200 vs write-path shed-to-503 policy (noted as revisitable in the entry comment).
Bounded by Postgres throughput, but ioxide proves ~2.6× headroom exists.
Fix location: frameworks/vanilla-epoll/main.v (pool/budget config) + possibly the pg_async pool defaults.
On
crud-4096, vanilla-epoll does 0.31M rps and emits 69,764 5xx while ioxide (C#) does 0.80M against the same Postgres — so the DB has headroom vanilla isn't using. The 503s are the async pool shedding when every pooled connection is atmax_inflight(frameworks/vanilla-epoll/main.v:288-294,acquire_pipelinedshed path ~:394); the shed is "honest", but the low rps + high shed rate suggests the per-worker pool size / pipelining depth (max_inflight) / worker-count split (main.v~:1300) is under-provisioned for this mix (75% GET-cached / 15% PUT / 5% list / 5% create).Investigate (medium confidence — the audit's verify pass was cut short):
max_inflightvs worker count, and theper_workerbudget split;Bounded by Postgres throughput, but ioxide proves ~2.6× headroom exists.
Fix location:
frameworks/vanilla-epoll/main.v(pool/budget config) + possibly thepg_asyncpool defaults.