Pagination and Streaming
Efficient data retrieval patterns for large datasets and real-time feeds. Let agents control how data flows.
Pagination Strategies
Cursor-Based Pagination
Most reliable for changing datasets. Uses opaque cursor for position tracking.
{
"tool": "list_orders",
"arguments": {
"limit": 50,
"cursor": "eyJpZCI6MTIzfQ==",
"direction": "forward"
}
}
// Response includes next cursor
{
"items": [...],
"next_cursor": "eyJpZCI6MTczfQ==",
"has_more": true
}Offset-Based Pagination
Simple but less stable. Good for static datasets.
{
"tool": "search_products",
"arguments": {
"page": 3,
"per_page": 20,
"sort": "created_at"
}
}
// Response with page metadata
{
"items": [...],
"page": 3,
"per_page": 20,
"total_pages": 15,
"total_items": 287
}Keyset Pagination
Uses actual data values for positioning. Efficient for large datasets.
{
"tool": "list_events",
"arguments": {
"limit": 100,
"after_id": "evt_8291",
"after_timestamp": "2025-08-25T10:00:00Z"
}
}Server-Sent Events (SSE)
Stream real-time updates and partial results as they become available:
SSE Stream Example
// Agent initiates stream
{
"tool": "stream_logs",
"arguments": {
"filter": "level:error",
"follow": true
}
}
// Server sends events
data: {"id":"log_1","level":"error","message":"Connection failed"}
data: {"id":"log_2","level":"error","message":"Retry attempted"}
event: done
data: {"total_events": 2, "session_id": "stream_abc123"}Event Types
- • data - Regular data event
- • progress - Progress update
- • error - Error notification
- • done - Stream complete
Stream Controls
- • Pause/resume capability
- • Backpressure handling
- • Automatic reconnection
- • Event buffering
Iteration Patterns
Progressive Loading
Load data incrementally as needed:
1. Load first page (10 items) 2. Process and check if more needed 3. Load next page if criteria met 4. Continue until done or limit reached
Parallel Pagination
Fetch multiple pages concurrently:
// After getting total pages Promise.all([ fetchPage(1), fetchPage(2), fetchPage(3) ])
Windowed Iteration
Process data in sliding windows:
Window 1: Items 0-99 Window 2: Items 50-149 (50% overlap) Window 3: Items 100-199 (50% overlap)
Advanced Features
Resumable Pagination
Save and restore pagination state:
{
"pagination_state": {
"cursor": "abc123",
"processed": 450,
"total": 1200
}
}Adaptive Page Size
Adjust page size based on performance:
if (latency > 500ms) {
page_size = Math.max(10, page_size / 2)
} else if (latency < 100ms) {
page_size = Math.min(200, page_size * 2)
}Configuration Example
{
"pagination": {
"default_strategy": "cursor",
"default_page_size": 50,
"max_page_size": 500,
"endpoints": {
"/api/orders": {
"strategy": "cursor",
"page_size": 100,
"sort_required": true
},
"/api/search": {
"strategy": "offset",
"max_results": 1000,
"deep_pagination_limit": 10000
},
"/api/events": {
"strategy": "keyset",
"key_fields": ["timestamp", "id"],
"supports_streaming": true
}
}
},
"streaming": {
"enabled": true,
"protocols": ["sse", "websocket"],
"heartbeat_interval": 30,
"reconnect_attempts": 3,
"buffer_size": 1000
}
}Best Practices
Use stable sort orders
Always include a unique field in sort to ensure consistent pagination
Implement page size limits
Protect your API from excessive page size requests
Provide total counts carefully
COUNT(*) can be expensive; consider estimates for large datasets
Stream for real-time data
Use SSE or WebSockets for live updates instead of polling
Efficient data retrieval at scale
MCPify handles pagination complexity so agents can focus on the data.