Логотип Workflow

Article

Updated at:

Stage 3: Pagination

Stage 3 - Pagination

Pagination exists because returning an unbounded list is dangerous. A table can grow from one hundred rows to ten million rows while the API contract still looks the same. Without pagination, one request can become slow, memory-heavy, and unstable for both server and client. Good pagination gives the client a predictable page size, a clear position in the result set, and enough metadata to request the next part without guessing.

Stage 3 - Pagination

The Problem This Solves

API design becomes important when more than one client depends on the same backend. A controller method can be easy to write and still be hard to use. The client needs names that match the domain, response bodies that do not change randomly, errors that are predictable, and list endpoints that keep working when data grows. Good API design is the difference between a server that merely responds and a product interface that teams can safely build on.

A useful way to think about this topic is contract first. The contract is not only a generated document. It is the promise that a request with a certain method, path, parameters, body, authentication state, and headers will receive a response with a known status code and shape. When a backend developer changes that promise without care, the frontend, mobile app, partner integration, or automated job can break even though the server still starts.

How To Think About It

Start with the business action, then translate it into API language. If the user wants to see orders, the resource is probably orders, not getOrdersData. If the user wants to cancel an order, check whether cancellation is a state change on an existing order, a sub-resource, or a domain command that needs its own endpoint. This decision should be visible in the URL, method, response code, and error format.

Do not optimize for cleverness. Optimize for the developer who opens the API six months later. Names should be boring and obvious. Optional parameters should have clear defaults. A response should include only what the client is allowed to know. Internal database names, stack traces, enum experiments, and temporary migration fields should not leak into the public contract unless they are deliberately part of it.

Concrete Example

GET /api/orders?status=PAID&page=0&size=20&sort=createdAt,desc
Accept: application/json

A clean endpoint like this tells a clear story. The client is asking for orders, not calling a backend function by name. The query parameters are explicit: one filter, one page request, and one sort rule. The server can validate those parameters, document them in OpenAPI, return a stable response shape, and use a consistent error format if the request is invalid.

Useful Reference

ConceptMeaning
pageZero-based or one-based page number
sizeMaximum items per page
totalElementsNumber of matching records when known
nextLink or cursor for the next page

Common Mistakes

  • Designing endpoints from controller method names instead of resource names.
  • Returning whatever the database entity currently looks like.
  • Treating validation, errors, pagination, and versioning as details to add later.
  • Changing response shapes without checking existing clients.
  • Documenting the API only after implementation, when the design is already hard to change.

Understanding Checklist

  • I can explain what contract this endpoint gives to a client.
  • I can name the request parameters and their allowed values.
  • I can describe successful and failed responses without reading backend code.
  • I can tell which changes would be breaking for an existing client.

Practice Before the Next Lesson

Design GET /orders?page=0&size=20 and describe what metadata the response should include.

Please login to pass quizzes.

Practice

Interactive practice

Complete tasks and check your answer instantly.