Summary
The audit and feed-item pruners do SELECT count(*) then a single unbatched DELETE ... WHERE cutoff in one transaction (src/iceberg/services/audit.py:225-232, src/iceberg/services/feeds.py:522-530). Config comments call AuditEvent "the fastest-growing table on a scanned public instance" (config.py:276-278).
Failure scenario
The first cron run on an existing instance (365-day window) can delete millions of rows in one statement: long row-lock hold, WAL/replication spike, potential job timeout, and on failure zero progress (no batched commits). The returned value is also the pre-delete count, not result.rowcount — a second full-table scan and a value that can drift from rows actually deleted.
Notes
FK integrity is fine — nothing references AuditEvent or FeedItem (their FKs point outward), and ingested feed items are correctly spared.
Suggested fix
Use a LIMIT-batched delete loop with per-batch commits (the standard shape for large retention deletes); return result.rowcount instead of a pre-count.
Found in Fable review of PR #232 → HEAD.
Summary
The audit and feed-item pruners do
SELECT count(*)then a single unbatchedDELETE ... WHERE cutoffin one transaction (src/iceberg/services/audit.py:225-232,src/iceberg/services/feeds.py:522-530). Config comments callAuditEvent"the fastest-growing table on a scanned public instance" (config.py:276-278).Failure scenario
The first cron run on an existing instance (365-day window) can delete millions of rows in one statement: long row-lock hold, WAL/replication spike, potential job timeout, and on failure zero progress (no batched commits). The returned value is also the pre-delete
count, notresult.rowcount— a second full-table scan and a value that can drift from rows actually deleted.Notes
FK integrity is fine — nothing references
AuditEventorFeedItem(their FKs point outward), and ingested feed items are correctly spared.Suggested fix
Use a
LIMIT-batched delete loop with per-batch commits (the standard shape for large retention deletes); returnresult.rowcountinstead of a pre-count.Found in Fable review of PR #232 → HEAD.