Files
ac4fa13b8e perf(relay): serve relay-membership checks from the read replica (#4124)
## Summary

Route `Db::is_relay_member` — the membership check that runs on every
authenticated HTTP request and WS AUTH — through the standard
`route_read` machinery on the bounded arm, instead of adding a bespoke
cache (replaces #3844).

- `crates/buzz-db/src/relay_members.rs`: add `is_relay_member_on(&mut
PgConnection, ...)` executor seam; the pool version delegates to it.
- `crates/buzz-db/src/lib.rs`: `Db::is_relay_member` now routes via
`route_read("relay_membership", RoutePredicate::Bounded)` — replica only
on a proved fresh session, writer on any route rejection, writer re-run
on replica query error. Exactly the shape of every other routed read.

This is the one permission read served from the replica, by explicit
product decision (Tyler accepted ≤1s bounded staleness on reads we
choose): the fleet-wide fence guarantee (`BUZZ_REPLICA_READ_MAX_AGE_MS`,
deploy target 1s) is an order of magnitude tighter than the 10s TTL
proposed in #3844 and needs no invalidation machinery. Staleness is
symmetric for admits and revokes. `BUZZ_REPLICA_READ_MAX_AGE_MS` unset =
writer-only = kill switch. It is not precedent for routing other
permission reads.

## Validation

At this exact commit (`git rev-parse HEAD` confirmed in the same shell,
rustc 1.95):

- `cargo test -p buzz-db` — 94 passed, 0 failed
- PG-gated suite single-threaded — **151 passed, 2 failed**; the 2
failures are the per-owner-limit tests broken on main by #3829 (limit
3→5, tests still seed 3) — they fail identically at base `19d57b0d4` in
a pristine control checkout; separate trivial fix to follow
- New PG-gated test `is_relay_member_is_bounded_routed_and_fails_closed`
— divergent writer/replica fixtures prove: budget unset ⇒ writer; budget
set + fresh proof ⇒ replica; over-budget entry ⇒ writer
- clippy `-D warnings` + fmt clean; pre-push hooks green (desktop
check/test, rust tests, tauri checks)
- **Live-local pass** (TESTING.md, release binary,
`BUZZ_REQUIRE_RELAY_MEMBERSHIP=true`, fresh DB):
- writer-only (no `READ_DATABASE_URL`): member accepted, outsider 403
`relay_membership_required`; metrics
`route_decision{path="relay_membership",decision="writer",reason="disabled"}`
- replica configured + `BUZZ_REPLICA_READ_MAX_AGE_MS=1000`: member
accepted / outsider denied via `decision="replica",reason="fresh"`;
admit visible to the routed check within ~1.2s; revoke enforced within
~1.2s
- reader outage mid-flight (TCP proxy killed): member send still
succeeds in <200ms via
`decision="writer",reason="reader_acquire_timeout"`; outsider still
denied — fails closed, no availability loss

Reviewed by Wren: 9/10 minimalness, 9/10 elegance, 9.5/10 correctness at
this SHA.

Supersedes the 10s-cache approach in PR 3844, which should be closed
unmerged once this lands.

Signed-off-by: Tyler <109685178+tlongwell-block@users.noreply.github.com>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
2026-08-01 13:32:16 -04:00
..
2026-07-27 14:18:24 -04:00