Reducing Count Query Cost in Pagination
What I Didn’t Know
While implementing pagination for the Gift API at Kakao Tech Campus, I used Spring Data JPA’s Page as the return type. Mentor told me something during code review:
“Page internally needs to know the total data count, so an additional count query runs.”
I didn’t know that using Page triggers SELECT COUNT(*) on every request.
Why Is Count Query Dangerous?
With small datasets, it’s fine. But with millions of rows, COUNT(*) can become a bottleneck.
For infinite scroll UI, total count isn’t needed. But if you use Page, you’re running unnecessary count queries.
Mentor feedback:
“Page exposes a lot of unnecessary information internally. totalPages, totalElements, sort, numberOfElements… If the client only needs some of this, there’s unnecessary serialization cost.”
“To avoid this, use Slice. Slice only determines if there’s a next page, so it doesn’t run a count query.”
Page vs Slice
| Property | Page | Slice |
|---|---|---|
| Count query | Runs | Doesn’t run |
| Total page count | Known | Unknown |
| Has next page | Known | Known |
| Best for | Page number UI | Infinite scroll, “Load more” |
When to Use What?
Page
- When you need page numbers like “1 2 3 4 5 … 100”
- When you need total count like “2,340 products total”
Slice
- Infinite scroll
- Just a “Load more” button
- When total count isn’t needed
Lessons Learned
- Learned that
Pagetriggers count queries - Use Slice when total count isn’t needed
- Need to understand what the framework does behind the scenes
From Kakao Tech Campus 3rd cohort Gift API clone coding, summarizing mentor feedback.