api-pagination
from aj-geddes/useful-ai-prompts
A curated collection of useful AI prompts for various tasks and use cases
50 stars4 forksUpdated Dec 28, 2025
npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill api-paginationSKILL.md
API Pagination
Overview
Implement scalable pagination strategies for handling large datasets with efficient querying, navigation, and performance optimization.
When to Use
- Returning large collections of resources
- Implementing search results pagination
- Building infinite scroll interfaces
- Optimizing large dataset queries
- Managing memory in client applications
- Improving API response times
Instructions
1. Offset/Limit Pagination
// Node.js offset/limit implementation
app.get('/api/users', async (req, res) => {
const page = parseInt(req.query.page) || 1;
const limit = Math.min(parseInt(req.query.limit) || 20, 100); // Max 100
const offset = (page - 1) * limit;
try {
const [users, total] = await Promise.all([
User.find()
.skip(offset)
.limit(limit)
.select('id email firstName lastName createdAt'),
User.countDocuments()
]);
const totalPages = Math.ceil(total / limit);
res.json({
data: users,
pagination: {
page,
limit,
total,
totalPages,
hasNext: page < totalPages,
hasPrev: page > 1
},
links: {
self: `/api/users?page=${page}&limit=${limit}`,
first: `/api/users?page=1&limit=${limit}`,
last: `/api/users?page=${totalPages}&limit=${limit}`,
...(page > 1 && { prev: `/api/users?page=${page - 1}&limit=${limit}` }),
...(page < totalPages && { next: `/api/users?page=${page + 1}&limit=${limit}` })
}
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Python offset/limit
from flask import request
from sqlalchemy import func
@app.route('/api/users', methods=['GET'])
def list_users():
page = request.args.get('page', 1, type=int)
limit = min(request.args.get('limit', 20, type=int), 100)
offset = (page - 1) * limit
total = db.session.query(func.count(User.id)).scalar()
users = db.session.query(User).offset(offset).limit(limit).all()
total_pages = (total + limit - 1) // limit
return jsonify({
'data': [u.to_dict() for u in users],
'pagination': {
'page': page,
'limit': limit,
'total': total,
'totalPages': total_pages,
'hasNext': page < total_pages,
'hasPrev': page > 1
}
}), 200
2. Cursor-Based Pagination
// Cursor-based pagination for better performance
class CursorPagination {
static encode(value) {
return Buffer.from(String(value)).toString('base64');
}
static decode(cursor) {
return Buffer.from(cursor, 'base64').toString('utf-8');
}
static generateCursor(resource) {
return this.encode(`${resource.id}:${resource.createdAt.getTime()}`);
}
static parseCursor(cursor) {
if (!cursor) return null;
const decoded = this.decode(cursor);
const [id, timestamp] = decoded.split(':');
return { id, timestamp: parseInt(timestamp) };
}
}
app.get('/api/users/cursor', async (req, res) => {
const limit = Math.min(parseInt(req.query.limit) || 20, 100);
const after = req.query.after ? CursorPagination.parseCursor(req.query.after) : null;
try {
const query = {};
if (after) {
query.createdAt = { $lt: new Date(after.timestamp) };
}
const users = await User.find(query)
.sort({ createdAt: -1, _id: -1 })
.limit(limit + 1)
.select('id email firstName lastName createdAt');
const hasMore = users.length > limit;
const data = hasMore ? users.slice(0, limit) : users;
const nextCursor = hasMore ? CursorPagination.generateCursor(data[data.length - 1]) : null;
res.json({
data,
pageInfo: {
hasNextPage: hasMore,
endCursor: nextCursor,
totalCount: await User.countDocuments()
},
links: {
self: `/api/users/cursor?limit=${limit}`,
next: nextCursor ? `/api/users/cursor?limit=${limit}&after=${nextCursor}` : null
}
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
3. Keyset Pagination
// Keyset pagination (most efficient for large datasets)
app.get('/api/products/keyset', async (req, res) => {
const limit = Math.min(parseInt(req.query.limit) || 20, 100);
const lastId = req.query.lastId;
const sortBy = req.query.sort || 'price'; // price or createdAt
try {
const query = {};
// Build query based on sort field
if (lastId) {
const lastProduct = await Product.findById(lastId);
if (sortBy === 'price') {
query.$or = [
{ price: { $lt: lastProduct.price } },
{ price: lastProduct.price, _id: { $lt: lastId } }
];
} else {
query.$or = [
{ createdAt: { $lt: lastProduct.createdAt } },
{ createdAt: lastProduct.createdAt, _id: { $lt: lastId } }
];
}
}
const products = await Product.find(query)
...
Repository Stats
Stars50
Forks4
LicenseMIT License