chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
getRepo lets other requests run while it reads the repo
MergedMerged as 1295d19
An atproto PDS in JavaScript, for Cloudflare Workers and Node
What changes
com.atproto.sync.getRepo, and the backup snapshot that sharesbuildFullRepoCar, wait on a timer after every 500 blocks the walk reads. Other requests run in those gaps.Why
On Cloudflare one Durable Object answers every request for the account.
buildFullRepoCarawaited only promises already settled, so it never let anything else in until the whole repo was read.microcosm's lightrail fetches the whole repo after any commit that deletes a collection's last record. That's a bug in lightrail: it can never prove such a death, so it resyncs. In prod on 2026-10-29,
wrangler tailshowed requests to chadtmiller.com's PDS waiting about 3.6 s behind lightrail'sgetRepo, then taking 14 ms once they ran. Organization clicks on knotless that came straight after a write took 8.6 s and 11.8 s instead of about 4.5 s.How it was checked
A new test in
test/xrpc-sync.test.jsrunsgetRepoover a 601-record repo, with a timer set to fire while it runs. The timer runs beforegetRepoends. Without the change, it runs after.npm run cipasses: 3242 tests, within the coverage floors.Benchmarked locally against better-sqlite3:
I also tried reading the blocks a tree level at a time, 100 to a query. It was no faster locally, and slower overall, so the walk keeps
getBlock.Shortcomings
wrangler tailduring an organization click after this deploys.getRepostill builds the whole CAR in memory before sending it.🤖 Generated with Claude Code