Enabling and Testing Pagination in FeathersJS Services
Turn on pagination in a FeathersJS service, test it with $limit and $skip, verify the response structure, and handle limit errors. Follow this step‑by‑step guide to avoid memory issues and ensure reliable API behavior.
25 Feb 2026, 02:40 UTC

What You’ll Achieve
By the end of this guide you will be able to turn on pagination for a FeathersJS service, query it with $limit and $skip, confirm the response structure, and recover from common misconfigurations.
Prerequisites
- Node.js 14+ and npm or yarn
- FeathersJS 6.x project (created with
feathers generate app) - Database adapter that supports pagination (e.g., Sequelize, Mongoose, or a custom adapter that implements the Feathers pagination interface)
- Administrative access to the database to verify record counts
Step‑by‑Step Procedure
1. Verify Adapter Pagination Support
Check that your chosen adapter implements the pagination interface. For Sequelize and Mongoose this is built‑in; for custom adapters you must expose find with paginate support.
2. Configure Service Pagination Options
In src/services/service/service.js set the paginate option. The default is { default: 10, max: 100 }.
module.exports = function (app) {
const options = {
paginate: {
default: 20,
max: 200
}
};
app.use('/posts', new PostsService(options));
};
3. Disable Pagination (Optional)
If you need to fetch the full dataset for a specific endpoint, set { paginate: false } in the service options or override it in a hook.
4. Send a Test GET Request
Use curl or a REST client to hit the service with pagination query parameters.
curl -X GET "http://localhost:3030/posts?&$limit=10&$skip=20&$sort[createdAt]=-1" -H "Content-Type: application/json"
Replace posts with your service name and adjust fields as needed.
5. Validate the Response Structure
Feathers returns an object with the following shape when pagination is active:
{
"total": 123,
"limit": 10,
"skip": 20,
"data": [
{ /* record 1 */ },
{ /* record 2 */ },
/* … */
]
}
Check that:
limitequals the requested$limit(or the service default if omitted)skipequals the requested$skip(or 0 if omitted)- The length of
datamatcheslimit(unless fewer records remain) totalmatches the count of all matching records in the database (useSELECT COUNT(*)or equivalent)
6. Test Error Handling for Excessive Limits
Request a limit greater than max to confirm a 400 error.
curl -X GET "http://localhost:3030/posts?&$limit=1000000" -H "Content-Type: application/json"
Expected response:
{
"code": 400,
"message": "$limit is too large. Max is 200.",
"data": {
"$limit": 1000000
}
}
7. Recovery Strategies
- Adjust
maxordefaultvalues: Edit thepaginateobject in the service options. - Override in a Hook: Use a before hook to clamp
params.query.$limitto a safe value. - Disable Pagination for Bulk Jobs: Set
{ paginate: false }when you need the full dataset. - Custom Adapter Implementation: If you’re using a non‑standard adapter, ensure its
findmethod returns an object withtotal,limit,skip, anddatafields.
Practical Verification Checklist
- Confirm the service returns
total,limit,skip, anddatawhen pagination is enabled. - Verify that
data.lengthnever exceedslimit. - Check that requesting beyond the dataset returns an empty
dataarray but still includestotal. - Ensure a 400 error occurs when
$limitexceedsmaxunless you explicitly override the check.
Conclusion
Pagination is a first‑class feature in FeathersJS, but it relies on adapter support and correct configuration. By following the steps above you can confidently enable pagination, validate your responses, and recover from common pitfalls.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.