ez.paginated() function generates ready-to-use schemas for both offset-based and cursor-based pagination.
Quick Start
Offset-Based Pagination
Offset pagination useslimit and offset parameters to navigate through results:
Request Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | defaultLimit | Number of items per page |
offset | number | 0 | Number of items to skip |
Response Shape
Cursor-Based Pagination
Cursor pagination uses an opaque cursor token to navigate through results:Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
cursor | string | No | Cursor for next page; omit for first page |
limit | number | No | Number of items per page (default: defaultLimit) |
Response Shape
Configuration Options
Theez.paginated() function accepts the following configuration:
Composing with Other Parameters
You can combine pagination schemas with additional filters using.and():
Complete Example
Here’s a full example from the Express Zod API source:Client-Side Usage
When you generate a TypeScript client, pagination endpoints get special helper methods:Offset vs Cursor: Which to Use?
Offset Pagination
Pros:- Simple to implement
- Supports jumping to arbitrary pages
- Shows total count of items
- Familiar UX (page numbers)
- Can miss or duplicate items if data changes between requests
- Performance degrades with large offsets
- Not suitable for real-time data
- Data is relatively static
- Users need to jump to specific pages
- Total count is important
- Dataset is small to medium sized
Cursor Pagination
Pros:- Consistent results even if data changes
- Performs well with large datasets
- Ideal for infinite scroll
- Good for real-time data
- Can’t jump to arbitrary pages
- No total count (without extra query)
- More complex to implement
- Implementing infinite scroll
- Data changes frequently
- Dataset is very large
- Page jumping isn’t needed
Best Practices
Set Reasonable Limits
Set
maxLimit to prevent clients from requesting too much data. 100-1000 is typical.Use Cursor for Large Datasets
For tables with millions of rows, cursor pagination performs much better than offset.
Include Total Count
For offset pagination, always return the total count so clients can show page numbers.
Document Cursor Format
If using cursor pagination, document what the cursor represents (even if it’s opaque).
Common Issues
Reserved Property Names
TheitemsName parameter cannot conflict with pagination metadata:
- Offset style reserves:
total,limit,offset - Cursor style reserves:
nextCursor,limit