REST API ページング設計で実務で迷いやすいポイント

REST API ページング設計でlimit offset、cursor pagination、sort、total countを整理する図

REST APIのページングは一覧画面の都合だけで決めない

REST API ページング設計で迷う場面は、実務ではかなり多いです。limitとoffsetで十分なのか。cursor paginationにすべきか。total countを毎回返すべきか。こうした判断は、一覧画面を表示できるかだけでは決まりません。

結論から言うと、ページング設計ではデータ量、並び順の安定性、総件数の必要性、フロントエンドの操作感を分けて考えることが重要です。特に検索条件が多い業務システムでは、最初に決めたレスポンス形式が長く使われます。

この記事では、REST APIの一覧取得を設計するエンジニア向けに、limit offset、cursor pagination、sort、total count、APIレスポンスの実務判断を整理します。薄い用語説明ではなく、レビューで見られやすい観点も扱います。

APIページング設計で最初に決めること

まず、ページング方式だけを先に決めると失敗しやすいです。画面の使い方、データの増え方、並び替えの種類を確認します。

観点確認すること設計への影響
データ量数千件か、数百万件かoffsetの深いページが重くなる
並び順登録日時、更新日時、スコアなど同値の並び替え条件が必要になる
画面操作ページ番号移動か、無限スクロールかoffset方式とcursor方式の向き不向きが変わる
総件数正確な件数が必要かcountクエリのコストが変わる
検索条件条件数とインデックス設計sortとwhereの組み合わせが重要になる

例えば、管理画面で「3ページ目へ移動したい」要件があるなら、offset方式は扱いやすいです。一方で、タイムラインや通知一覧のように次の塊を順番に読む画面なら、cursor方式が向いています。

クエリパラメータを設計するときは、MDNのURLSearchParamsのように、URLのquery stringとしてどう扱われるかも意識します。フロントエンド側で検索条件を組み立てやすい命名にします。

limit offsetはわかりやすいが深いページに注意する

limit offset方式は、実装者にも利用者にも理解しやすい方式です。例えば、次のようなAPIです。

GET /api/orders?limit=50&offset=100&sort=createdAt,desc

ただし、offsetが大きくなるほどDB側の負荷が増えることがあります。特に複雑なwhere条件、join、ソートが絡む一覧では、見た目以上に重いSQLになります。

そのため、limit offsetを採用する場合は上限を決めます。例えば、limitの最大値を100にする。offsetが一定以上の検索には条件追加を促す。重い一覧では非同期出力に切り替える。こうした運用上の線引きも設計に含めます。

cursor paginationは順次取得に強い

cursor paginationは、次のページを取得するためのカーソルをレスポンスで返す方式です。ページ番号移動よりも、前回取得した位置から続きを読む用途に向いています。

GET /api/orders?limit=50&cursor=eyJjcmVhdGVkQXQiOiIyMDI2LTA2LTA0VDA5OjAwOjAwWiIsImlkIjoxMjM0fQ

cursor方式では、並び順とカーソルの中身を一貫させる必要があります。createdAtだけを基準にすると、同じ時刻のデータで順序が不安定になります。そのため、createdAtとidのように一意性を補う条件を持たせます。

JSON:APIのCursor Pagination Profileでも、cursorを使ったページングの考え方が整理されています。仕様をそのまま採用しない場合でも、次ページ、前ページ、並び順の扱いを考える参考になります。

sortはページング設計の一部として扱う

ページングでよくある失敗は、sortを後付けで増やすことです。並び順が変わると、ページの境界も変わります。つまり、sortは表示オプションではなく、ページング設計の一部です。

{
  "items": [
    { "id": 1234, "createdAt": "2026-06-04T09:00:00Z", "status": "APPROVED" }
  ],
  "page": {
    "limit": 50,
    "nextCursor": "eyJjcmVhdGVkQXQiOiIyMDI2LTA2LTA0VDA5OjAwOjAwWiIsImlkIjoxMjM0fQ",
    "hasNext": true
  },
  "sort": [
    { "field": "createdAt", "direction": "desc" },
    { "field": "id", "direction": "desc" }
  ]
}

この例では、createdAtだけでなくidも並び順に含めています。これにより、同じcreatedAtのレコードが複数あっても順序が安定します。

なお、OpenAPIで一覧APIを定義する場合は、query parameterとしてlimit、offset、cursor、sortを明示します。OpenAPI LearnのParameters and Payload of an Operationでは、operationのparameter定義が整理されています。

total countは毎回返せばよいとは限らない

総件数は便利です。画面に「全1,234件」と表示できます。ページ番号UIも作りやすくなります。

一方で、countクエリは重くなることがあります。検索条件が複雑で、joinや権限制御も入る場合、一覧取得よりcountの方が遅いこともあります。

実務では、次のように分けると判断しやすいです。

要件total countの扱い理由
業務上、件数確認が重要返す承認対象件数や請求対象件数に使う
無限スクロール返さない、または概算次があるかだけで足りる
重い検索条件別API、遅延取得を検討初期表示を遅くしない
監査や帳票一覧APIとは分ける正確性と処理時間の要件が違う

レビューで見るREST API ページング設計のチェックリスト

  • limitの最大値が決まっているか
  • offset方式とcursor方式の採用理由を説明できるか
  • sortの指定可能項目が明確か
  • 同値ソート時の順序が安定しているか
  • total countの必要性とコストを確認しているか
  • レスポンスにhasNext、nextCursor、limitなどのメタ情報があるか
  • 検索条件、認可条件、インデックスの組み合わせを確認しているか

よくある質問

一覧APIは最初からcursor paginationにすべきですか?

必ずしもそうではありません。ページ番号移動が必要な管理画面では、limit offset方式の方が扱いやすいことがあります。一方で、大量データを時系列で読み進める画面ではcursor方式が向いています。

total countを返さないと画面が不親切ですか?

画面要件によります。業務上の件数確認が重要なら返す価値があります。ただし、単に次ページがあるか知りたいだけなら、hasNextで足りる場合があります。

まとめ

REST APIのページング設計では、limit offsetとcursor paginationの優劣だけで決めないことが重要です。データ量、並び順、画面操作、total countのコストを分けて判断します。

  • limit offsetはわかりやすいが、深いページと重い検索条件に注意する
  • cursor paginationは順次取得に強いが、安定したsort設計が必要
  • total countは便利だが、毎回返す前提にしない

Java/Spring BootやReactの案件では、一覧APIの設計力が開発効率に直結します。ページング、検索、ソート、レスポンス形式まで説明できる経験は、現場での信頼にもつながります。

API設計やSpring Boot案件で、今の経験をどう活かすか整理したい場合は、技術領域や働き方の希望も含めて相談できます。

IaC INP PM PMO PMP UX Webディレクター インフラエンジニア キャリアチェンジ フロントエンドエンジニア