Spring Boot Pagination with Pageable, Page, and Slice

Implement production-ready pagination in Spring Boot with Pageable, Page, Slice, and best practices for efficient large dataset handling.

Last reviewed: November 2026

·Spring Boot 2.7Spring Boot 3.x
✅
Quick Understanding: Spring Boot pagination uses Pageable for the incoming page, size, and sort request, while Page or Slice shape the response. It is the standard way to keep REST list endpoints fast, bounded, and production-safe.

🔍 What Is It?

Spring pagination in Spring Boot is the pattern used to split large result sets into manageable API responses. If you search for "Spring Boot pagination," the direct answer is that Pageable, Page<T>, and Slice<T> are the main abstractions used to request and return paginated data, most often through Spring Data JPA.

Quick Facts

  • →Used in: REST list endpoints, admin dashboards, search results, and mobile infinite-scroll APIs
  • →Best for: Returning large datasets safely without unbounded memory or payload growth
  • →Interview importance: High because pagination is a common Spring Data and API design topic
  • →Production relevance: High because list endpoints break down quickly without paging rules
  • →Related topics: Spring Data JPA, repositories, entity mapping, controllers

Core abstractions

  • →Pageable - the request object with page number, size, and sort
  • →Page<T> - the response object with content, total count, and pagination metadata
  • →Slice<T> - a lighter response that skips the total count query and only tells you whether another page exists

Common pagination details

  • →Page numbers are 0-indexed by default
  • →Sort rules can be passed through request params or created in code
  • →PageRequest.of(page, size, sort) is the standard programmatic constructor

🎯 Why Do We Need It?

Without pagination, list endpoints return too much data, create slow database queries, and make API consumers harder to support. Pagination is one of the first production protections every serious backend should implement.

Interview Relevance

  • →Interviewers ask pagination to test whether you understand API design, database load, and Spring Data behavior
  • →Strong answers explain Page versus Slice, max page size enforcement, and why deep offset pagination becomes expensive
  • →Senior answers usually connect pagination to indexing, sorting, and client-specific UX patterns such as infinite scroll

🏗️ What Happens in Real Projects?

Production Usage

Pagination is used on nearly every bounded list endpoint:

  • →GET /api/v1/orders?page=0&size=20&sort=createdAt,desc
  • →GET /api/v1/products?category=electronics&page=0&size=50
  • →Admin dashboards showing paginated tables
  • →Mobile apps using infinite scroll with Slice

Teams also use pagination rules to enforce fair API usage, prevent oversized responses, and keep database queries predictable as tables grow.

⚙️ How It Works

With Spring Data JPA, a paged repository query applies an offset and a maximum result size; the JPA provider translates that into database-specific paging syntax. A Page<T> may need an additional count query for total elements and total pages. Spring Data can omit that count when it can infer the total from the returned data. A Slice<T> typically fetches one extra row to check whether another slice exists without calculating a full total.

Pageable vs Page vs Slice

  • →Pageable describes the incoming request: page number, page size, and sort
  • →Page<T> returns content plus total count metadata
  • →Slice<T> returns content plus only enough information to know whether another page exists

Stable sorting and input limits

Always sort deterministically. If several records share createdAt, add a unique tie-breaker such as id. Reject negative pages and non-positive sizes, cap the maximum size, and allow only supported sort properties. Offset pagination can still shift when rows are inserted or removed; keyset pagination is a better fit for deep, changing feeds.

💻 Example

Pagination in Practice — Repository, service, and controller with full pagination support.

java
// Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
    Page<Order> findByCustomerIdAndStatus(
        Long customerId, OrderStatus status, Pageable pageable);

    // Slice for infinite scroll (no COUNT query)
    Slice<Order> findByStatus(OrderStatus status, Pageable pageable);
}

// Service
@Service
@Transactional(readOnly = true)
public class OrderService {

    public Page<OrderSummaryDto> getCustomerOrders(
            Long customerId, OrderStatus status, int page, int size, String sortBy) {

        if (page < 0 || size < 1) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid page or size");
        }
        if (!Set.of("createdAt", "id").contains(sortBy)) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Unsupported sort property");
        }
        int validSize = Math.min(size, 100);
        Sort sort = Sort.by(Sort.Direction.DESC, sortBy);
        if (!"id".equals(sortBy)) {
            sort = sort.and(Sort.by(Sort.Direction.DESC, "id"));
        }
        Pageable pageable = PageRequest.of(page, validSize, sort);

        return orderRepository
            .findByCustomerIdAndStatus(customerId, status, pageable)
            .map(OrderSummaryDto::from);
    }
}

// Controller
@GetMapping
public ResponseEntity<Page<OrderSummaryDto>> getOrders(
        @RequestParam(name = "page", defaultValue = "0") int page,
        @RequestParam(name = "size", defaultValue = "20") int size,
        @RequestParam(name = "sortBy", defaultValue = "createdAt") String sortBy,
        @RequestParam(name = "status", defaultValue = "PENDING") OrderStatus status,
        @AuthenticationPrincipal UserDetails user) {

    Page<OrderSummaryDto> orders = orderService.getCustomerOrders(
        userService.getIdByUsername(user.getUsername()), status, page, size, sortBy);

    return ResponseEntity.ok(orders);
}

🤔 Common Confusions

❓ Page vs Slice - when should I use which?

Page provides total elements and total pages, which can require a separate count query. Slice provides content and whether another slice exists without calculating the full total, which is often better for infinite scroll.

❓ Is Spring Data pagination 0-indexed or 1-indexed?

Spring Data pagination is 0-indexed by default. Page 0 is the first page unless you intentionally configure a different resolver behavior.

🚨 Common Production Issues

Count queries on large tables with complex filters can become slower than the data query itself.

Missing maximum page size enforcement can let clients request huge payloads that hurt performance.

Deep offset pagination becomes expensive because the database still scans past many rows before returning the requested page.

Sorting on unindexed fields can turn a paginated endpoint into a full table scan.

✅ Best Practices

Always enforce a sensible maximum page size such as 100.

Use Slice instead of Page when the client does not need a full count.

Index the columns that your pagination sort relies on.

Use cursor or keyset pagination for very large datasets or deep scrolling flows.

Map entities to DTOs instead of returning JPA entities directly from paginated endpoints.

🏛️ Architect's Note

Senior Architect's Perspective

Offset-based pagination is simple, but it degrades on very deep pages because the database still has to skip a large number of rows. For high-scale event streams, logs, or time-series style data, cursor-based pagination is often the more durable production choice.

💬 Frequently Asked Questions

What is the difference between Pageable, Page, and Slice?

Pageable describes the requested page number, size, and sorting. Page and Slice are results: Page includes total-count metadata, while Slice includes whether another chunk exists without requiring a full count.

How do I set a maximum size for request-bound Pageable?

For Spring Boot auto-configured Spring Data web support, configure spring.data.web.pageable.max-page-size. A PageableDefault annotation supplies defaults, but does not set a hard maximum. Validate or cap sizes separately when constructing PageRequest yourself.

Why can paginated results contain duplicates or missing records?

Sorting by a non-unique field can produce an unstable order. Add a unique tie-breaker such as id. Inserts and deletions can also shift offsets between requests, so a stable sort alone does not provide snapshot consistency; use an appropriate cursor or consistency strategy when needed.

How do I sort by multiple fields?

Use Sort.by with multiple Sort.Order values, or send repeated sort query params such as ?sort=createdAt,desc&sort=lastName,asc.

Why is pagination important in Spring Boot interviews?

Interviewers use pagination to test whether you understand bounded APIs, Spring Data abstractions, and the database trade-offs behind large result sets.

When should I use Slice instead of Page?

Use Slice when the client only needs the current chunk and whether another page exists, such as infinite scroll or lightweight feed APIs.

What is the main production risk with deep pagination?

Deep offset pagination gets slower as the page number grows because the database must scan and discard more rows before returning the page you asked for.

🎯 Key Takeaways

1Pageable defines the paging request, while Page and Slice define the shaped response.
2Every production list endpoint should be bounded with page size rules.
3Page is useful for total-count UIs, and Slice is useful for lighter scroll-based flows.
4Sorting and indexing decisions directly affect pagination performance.
5Cursor-based pagination is often better for very large or very deep datasets.

🎯 Practice this topic in interviews

↗ Where this topic fits

Sources

Sources / References

Use these Spring Boot references to verify the concept in official docs and continue into the most relevant SplashRide pages.

Related SplashRide pages

SplashRide Spring Boot learning path

Browse the full Spring Boot topic collection and learning order on SplashRide.

Spring Boot Interview Prep

Practice Spring Boot interview questions and scenario-based answers.

Backend Engineer Career Path

A structured journey through Core Java, Spring Boot, production backend engineering, and interview preparation.

Full Stack Java Developer Career Path

A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.

Spring Data JPA

Master Spring Data JPA — the abstraction layer over Hibernate that eliminates boilerplate data access code through repository interfaces and derived query methods.

Repositories

Master the Spring Data repository pattern — from basic JpaRepository to custom implementations, projections, and the repository design best practices for enterprise applications.