Compliance staff waited about three seconds every time they opened the moderation queue. The rows on screen took tens of milliseconds.
It was a KYC review queue: applications, filters on status and date, fifty per page. I profiled it expecting a bad join or a missing index. The page query was fine. Almost all of the wait came from one line that had gone unexamined, the total count behind the pager.
Each filter combination made that count walk the whole filtered set, just so the interface could print "page 1 of 1,400". Showing fifty applications was cheap. Knowing how many applications existed was the entire response time.
So I stopped answering that question. Keyset pagination on created_at plus id: the next page is a seek from the last row you saw, not an offset the database has to count past. The total became a capped probe. Look for a bit more than a thousand, and if they are there, the interface says 1000+. Three seconds down to roughly 200ms, and deep pages got faster instead of worse, which offset pagination does not manage.
The code took an afternoon. The conversation took longer. Someone has to accept losing jump-to-page and the exact total. In an internal work queue that was easy: moderators rarely jump to page 47, they filter. In a customer-facing catalog I would have argued much harder, or kept an approximate count maintained on write.
What I take from it: a lot of the latency I remove is not work done badly. It is work few people need, rendered in a control that mostly sits unused.
I write these up as I hit them, with more of the reasoning than fits here: https://polycratia.com/c/6f8aea57
If your list endpoints return an exact total, worth checking whether that is a real product requirement, or whether it probably arrived with a UI component...