posts/0020.md · 2026-04-23
oxipool — a sharded connection pooler for OxiDB
PgBouncer for OxiDB. Single binary, written in Tokio. Accepts client connections on one port, multiplexes them onto a smaller pool of backend connections to one or more oxidb-server nodes. Two modes: pooling (route any client to any free backend) and sharded (hash the doc id, pick the right backend).
**Hash sharding.** `OXIPOOL_BACKENDS="1=host1:4444,2=host2:4444,3=host3:4444"`, `OXIPOOL_SHARD_KEY="_id"` and you get consistent-hashing routing. Each shard runs its own OxiDB. Cross-shard queries (find without a shard-key predicate) fan out + merge; same-shard queries stay on a single backend with full transaction support.
**The recent merge bug.** Found by the 100K load test: stale-pool conn to a freshly-restarted follower returned an error → router silently dropped that shard's results → `count(*)` returned ~2/3 of actual rows. The fix added `first_partial_error` to every merge — `merge_counts`, `merge_doc_arrays`, `merge_modified` — so the router fails fast with the offending shard's message instead of silently producing wrong answers.
**Health checks.** Background pinger drops dead backends out of the pool; replacements re-handshake when they come back. A bounded `Ping` timeout (2s) on pool checkout catches half-dead TCP connections that didn't get a clean FIN — without it, you'd wait the OS keepalive interval (~2h on macOS/Linux) before noticing.
**oxipool itself is a workspace crate** — same repo, same release cycle. Latest tag is 0.25.3.