read benchmark — 2026-06-12#
scripts/bench-reads: identical seeded workload (5 flows, 300 flow runs,
~870 writes via the REST API, seed 1337), then 30 iterations per read
pattern, sequential, same machine (macOS arm64 M3 Max). weir is a
ReleaseFast-equivalent debug build? no — debug build; python 3.7.4 via
uv run. pattern names mirror profile_queries.py in
prefectlabs/object-store-orchestration.
| pattern | weir p50/p95 | python+sqlite p50/p95 | python+postgres p50/p95 |
|---|---|---|---|
| seed write rate | 184–202/s | 160/s | 163/s |
| point_lookup | 0.2 / 0.3 | 1.7 / 2.3 | 2.6 / 3.3 |
| active_by_state | 1.0 / 1.2 | 4.4 / 5.5 | 4.7 / 5.2 |
| completed_50 | 5.5 / 5.9 | 5.8 / 6.5 | 6.7 / 7.2 |
| paginated (offset 100) | 5.5 / 5.6 | 6.0 / 7.5 | 6.8 / 7.0 |
| count_completed | 0.2 / 0.3 | 1.3 / 1.8 | 2.1 / 2.7 |
| flow_list | 0.4 / 0.5 | 3.4 / 4.2 | 4.5 / 4.9 |
(milliseconds; python columns from separate runs against fresh stores.)
reading the table#
- membership-set reads (point, count, active, list) are 4–11× faster than python against either database — they never leave process memory. this is the cloud prototype's "redis answers the orchestration plane" band, reproduced in miniature.
- bulk list reads are nearly tied (5.5 vs 5.8–6.8 ms). ours loads all candidates then sorts and slices (O(candidates)); sqlite/postgres push LIMIT down. at 268 completed runs the costs coincide; at 10⁵ they won't. the fix when it matters: a created-time zset so the slice happens before the row loads.
- write rate: 184–202/s with the repo doing a signed commit + full CAR rewrite on every mutation — and it still edges out python's 160/s. signing is not the bottleneck (~0.07ms); the CAR rewrite is, and it's the known-naive part (block-level append is the designed fix).
reference points from the cloud prototype (not comparable, but orienting)#
their GKE simulation runs a p95/whale workspace (~440 writes/s continuous,
millions of terminal rows) over networked GCS + redis:
active_by_state 14ms, deployment reads 5ms, completed_24h 279ms,
delta-merge-heavy task-run scans 869ms. different scale, different
infrastructure, different question — theirs is "does the three-plane
architecture hold at whale scale," ours is "does the atproto-canonical
architecture cost anything at workspace scale." the answer so far: no —
the appview makes reads competitive-to-faster, and the canonical layer
taxes writes ~0 at this scale even with naive persistence.
their open item — "we haven't run the same queries against the production Postgres" — is partially served here at small scale: python+postgres loses to python+sqlite on every pattern at n=300 (network hop dominates), which is itself a reminder that these comparisons only mean something within a scale class.
caveats#
- single machine, sequential requests, demo scale (300 runs), one run per target. variance not characterized.
- weir is a Debug build — its numbers would only improve.
- python servers measured through uvicorn + pydantic validation; that's the product surface, not the database. this benchmarks architectures end-to-end, not storage engines.
- no time-window patterns yet (
completed_1h-style) — needs TID-range scans or a time zset on our side.