com.atproto.repo.listRecords now spends the same per-address sync budget and in-flight turn as getRecord and the com.atproto.sync reads, so a burst from one address with no credential is refused with a 429 rather than queueing on the server. It reads its page on the blocking pool, as one of the 32 shared sync reads, one record at a time. A page ends early with a cursor once its JSON body would pass [capacity] list_records_page_bytes (default 4 MiB, range 1 MiB to 32 MiB), and it always holds at least one record, so a client that pages still reads everything.
New tests fail on main: a held listing from one address leaves a second address answered while the first address's next listing is refused; listings spend the per-minute budget; and a page ends at its byte budget while paging still reads every record once.
No deploy window is needed: this is an ordinary release with no data layout change, and rolling back is safe.
Closes https://tangled.org/permadeath.com/didbot/issues/242
🤖 Generated with Claude Code