How to handle pagination in Node.js APIs
Implementing pagination is crucial for Node.js APIs that handle large datasets, preventing performance issues and improving user experience. As the creator of CoreUI with over 11 years of Node.js development experience since 2014, I’ve built pagination into hundreds of enterprise APIs. The most effective solution is to use limit and offset query parameters with proper response metadata including total count and page information. This approach is efficient, scalable, and follows REST API best practices.
Use limit and offset parameters to implement pagination in Node.js APIs.
const express = require('express')
const { User } = require('./models')
const app = express()
app.get('/api/users', async (req, res) => {
const page = parseInt(req.query.page) || 1
const limit = parseInt(req.query.limit) || 10
const offset = (page - 1) * limit
const { count, rows } = await User.findAndCountAll({
limit,
offset,
order: [['createdAt', 'DESC']]
})
res.json({
data: rows,
pagination: {
total: count,
page,
limit,
totalPages: Math.ceil(count / limit)
}
})
})
The API accepts page and limit query parameters, defaulting to page 1 and 10 items per page. The offset is calculated as (page - 1) * limit to skip previous pages. Sequelize’s findAndCountAll() returns both the data rows and total count in one query. The response includes both the data and pagination metadata, allowing clients to build pagination controls with total pages, current page, and item counts.
Best Practice Note
This is the same pagination pattern we use in CoreUI backend APIs for dashboards and data tables. For better performance with very large datasets, consider cursor-based pagination using timestamps or IDs instead of offset, as offset becomes slower with higher page numbers.



