The merger's neighbour query matched "end_id = ? OR start_id = ?", which no index serves: it read every range of the group per file, 5.5 s a round and most of Postgres's time in an end-to-end run. Now the range holding the article before and after, by (group_id, start_id): 0.08 ms. The prefetcher's leased and started ranges (every 2 s) get partial indexes: 15-25 ms -> <0.1 ms with 145k planned ranges. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>