Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring Data JPA Page versus Slice: pay for totals only when needed

Last updated: 5 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

A Slice reports whether another window exists without the total-count work a Page may require.

Match the return type to the screen

An activity feed needs 47 receipts and a next button. It does not display an exact page count. Returning Page asks the repository infrastructure for total metadata and can issue a count query; returning Slice fetches enough rows to determine whether another slice exists. That saves count work, but it does not make the data query free. Use a deliberate count query when an admin report truly needs an exact total.

Use a deterministic order

Ordering only by createdAt is unstable when two receipts share a timestamp. Add id as a tie-breaker, and keep both columns in the query's order. With offset pagination, a new row inserted between requests can still shift later results. For deep scrolling or strong continuation semantics, use a keyset cursor with an index matching the filter and order.

Prove the query budget

Request the first and second slices from a dataset larger than one page; assert hasNext is accurate and IDs do not repeat in the unchanged dataset. Record the SQL. Then request a large offset to observe the database work, and cap page size with input bounds. A Slice is a count-cost choice, not a cure for deep offset scans.

Implementation contract

Java
interface ReceiptFeedRepository extends JpaRepository<ReceiptEntity, UUID> {
    Slice<ReceiptEntity> findByTenantId(
        UUID tenantId, Pageable page);
}

Pageable firstWindow = PageRequest.of(0, 47,
    Sort.by(Sort.Order.desc("createdAt"),
            Sort.Order.desc("id")));

Cost and verification

A Slice typically reads one extra row to determine hasNext. A Page can require a separate count query, especially expensive with joins. Both offset forms may scan or skip increasing work as the requested page number grows.

Common Mistakes

  • Do not request Page totals for a screen that never displays them.
  • Do not sort on a non-unique timestamp alone.
  • Do not describe Slice as keyset pagination; it still uses an offset with Pageable.

Read next

Spring Data JPA count query for a joined Page, Spring Data keyset pagination: continue after the last stable identifier, Spring API pagination: bounded requests and immutable snapshots, Spring Data JPA Specifications with a mandatory tenant predicate, Spring Data JPA entity graph for a bounded to-one read.

Related data contract

JPA collection batch fetching: reduce N+1 without a giant join.

spring
spring-data-jpa
jpa-page-vs-slice
Storage details