Implementing Scalable Pagination and Sorting in JHipster Applications
Learn how JHipster implements Spring Data JPA pagination and sorting to prevent memory exhaustion and optimize database performance in REST APIs.
30 Sept 2025, 20:10 UTC

The Problem: Unbounded Result Sets
Returning a full entity list from a JHipster REST API works for small tables but causes OutOfMemoryErrors and client crashes as data grows to hundreds of thousands of rows. JHipster prevents this by defaulting to Spring Data JPA pagination so each request transfers a bounded slice.
Architectural Requirements
A production pagination system must protect resources, allow client control, and expose metadata.
- Resource protection: Cap records per request.
- Client control: Allow page, size and sort selection.
- Metadata transparency: Return totalElements and totalPages for UI controls.
Smallest Suitable Design
JHipster uses Spring Data Pageable to keep pagination logic in the repository layer.
- REST Controller: Accepts page, size and sort query parameters.
- Service Layer: Receives Pageable and delegates to repository.
- Repository Layer: Extends JpaRepository which inherits PagingAndSortingRepository.
- DTO Mapping: Page<Entity> is mapped to Page<DTO> via MapStruct before response.
Generated shape
A generated controller method typically looks like:
@GetMapping("/api/products")
public ResponseEntity<Page<ProductDTO>> getAllProducts(Pageable pageable) {
Page<ProductDTO> page = productService.findAll(pageable);
return ResponseEntity.ok().body(page);
}Request example to run against a local instance:
curl "http://localhost:8080/api/products?page=1&size=20&sort=name,desc"The response is a JSON object with content array and metadata fields totalPages, totalElements and number.
Trust and Data Boundaries
Pageable is built from client query parameters and mapped to SQL ORDER BY and LIMIT/OFFSET. Sorting on a non-indexed column forces a full table scan. Data boundaries are enforced by mapping entities to DTOs with MapStruct so internal schema is not exposed.
Verify sortable fields correspond to indexed columns. In JDL, mark frequently sorted fields as indexed where supported.
Operational Checks and Failure Modes
Deep pagination latency
Relational databases implement pagination with OFFSET. Requesting page=10000 size=20 forces scanning ~200,000 rows before returning results, causing linear degradation.
Uncapped size
Without a maximum, a request with size=1000000 can allocate a large DTO list and trigger OutOfMemoryError.
Verification check: request a large size such as 10000. If the server returns all records without capping or 400 error, add a global maximum via application.yml or a custom PageableHandlerMethodArgumentResolver.
Conditions That Change the Design
Spring Data offset pagination is suitable for most business apps. Move to keyset or cursor pagination when datasets exceed millions of rows, users routinely access deep pages, or data churn causes shifting results across pages.
Rollback note: pagination behavior is generated from JDL. Regenerating an entity with jhipster entity <EntityName> will overwrite manual controller and service changes.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.