Koa Query Parameter Pagination Middleware

raw JSON →
1.3.2 verified Thu Apr 23 auth: no javascript maintenance

koa-pagination-v2 is a middleware designed for Koa applications to simplify handling pagination logic based on `page` and `limit` query parameters from the request. Currently at version 1.3.2, this package was last published approximately four years ago, indicating it is in a maintenance state rather than active development, with no recent releases or active contribution. Unlike its predecessor or other Koa pagination libraries that might focus on HTTP Range headers (e.g., the original `koa-pagination`), this version specifically processes `page` and `limit` from the URL query string. It exposes computed `limit` and `offset` values, along with a `pageable` helper function, via `ctx.state.paginate`. These values are directly usable with common ORMs (like Sequelize, as shown in the examples) to fetch a subset of data, and the `pageable` function helps construct comprehensive pagination metadata for API responses, including total count, page count, and navigation links. Its key differentiator is its straightforward, query-parameter-based approach, making it easy to integrate for simple REST API pagination.

error TypeError: ctx.state.paginate is undefined
cause The `koa-pagination-v2` middleware has not been correctly applied to the Koa application via `app.use(pagination())` before the route handler attempts to access `ctx.state.paginate`.
fix
Ensure app.use(pagination({ /* config */ })); is called *before* any route handlers that depend on pagination data.
error Incorrect pagination metadata (e.g., `pageCount` is 1 when it should be higher)
cause The `total` count passed to `ctx.state.paginate.pageable(total)` is incorrect or missing. This usually happens if the total count is not fetched from the database or if a filtered count is not used.
fix
Verify that your database query correctly returns the *total* number of records matching any filters, ignoring the limit and offset for the actual data retrieval, and pass this accurate total to the pageable function.
error User-requested `limit` parameter is not respected in the response
cause The `limit` parameter in the request query might exceed the `maximumLimit` configured in the middleware, or `defaultLimit` is being incorrectly used.
fix
Check the maximumLimit option provided when initializing the koa-pagination-v2 middleware. The middleware will cap the limit at this maximum, even if a higher value is requested by the client.
gotcha This package, `koa-pagination-v2`, processes `page` and `limit` query parameters. Be aware that it is distinct from other `koa-pagination` packages (e.g., `koa-pagination` by Uphold) that parse HTTP `Range` headers for pagination. Using them interchangeably will lead to unexpected behavior.
fix Ensure you understand whether your API expects query parameters (`page`, `limit`) or HTTP `Range` headers, and choose the appropriate middleware. If migrating, update client-side pagination logic accordingly.
gotcha The package was last published over four years ago (as of April 2026). While it generally works, it may not receive updates for new Koa versions, Node.js features, or critical security patches. Consider its maintenance status for long-term project viability.
fix Evaluate alternatives if active maintenance and modern feature support are critical for your project. If using, ensure thorough testing with your specific Koa and Node.js versions.
gotcha The `pageable` helper function, exposed on `ctx.state.paginate`, requires the total count of items in the dataset as an argument (`pageable(total)`). If `total` is not provided or is incorrect, the generated `_meta` object in the response will contain inaccurate pagination information (e.g., `pageCount`, `hasNext`).
fix Always ensure that your data fetching logic accurately determines the total count of items that match the query *before* pagination is applied, and pass this `total` count to `ctx.state.paginate.pageable()`.
breaking The configuration options `defaultLimit` and `maximumLimit` affect how `limit` and `offset` are calculated. If `maximumLimit` is set too low, user-requested limits might be silently capped, leading to unexpected results if not communicated to the client.
fix Carefully choose `defaultLimit` and `maximumLimit` values to align with your API's design and expected usage. Clearly document these limits for API consumers so they understand the effective pagination behavior.
npm install koa-pagination-v2
yarn add koa-pagination-v2
pnpm add koa-pagination-v2

This quickstart demonstrates how to apply `koa-pagination-v2` middleware to a Koa application, fetch paginated data using mock data, and return a response with pagination metadata. It shows accessing `limit`, `offset`, and the `pageable` helper from `ctx.state.paginate`.

const Koa = require('koa');
const pagination = require('koa-pagination-v2');

const app = new Koa();

// Mock database function for demonstration
const mockFindAndCountAll = async ({ offset, limit }) => {
    const allItems = Array.from({ length: 100 }, (_, i) => ({ id: i + 1, name: `Item ${i + 1}` }));
    const rows = allItems.slice(offset, offset + limit);
    const count = allItems.length;
    return { rows, count };
};

app.use(pagination({ defaultLimit: 10, maximumLimit: 50 }));

app.use(async ctx => {
    if (ctx.path === '/items') {
        const { limit, offset, pageable } = ctx.state.paginate;

        const { rows: items, count: total } = await mockFindAndCountAll({
            offset,
            limit
        });

        ctx.body = {
            data: items,
            _meta: pageable(total) // Pass the total count to generate meta-data
        };
    } else {
        ctx.body = 'Visit /items?page=1&limit=10 for pagination example.';
    }
});

const port = process.env.PORT || 3000;
app.listen(port, () => {
    console.log(`Server running on http://localhost:${port}`);
    console.log(`Try: http://localhost:${port}/items?page=1&limit=5`);
    console.log(`Try: http://localhost:${port}/items?page=2&limit=5`);
    console.log(`Try: http://localhost:${port}/items?page=1&limit=60 (will cap at maxLimit of 50)`);
});