この記事の最終更新日: 2026年8月1日

REST APIについて学んでいると、必ずと言っていいほど出てくる言葉があります。
それが 「ステートレス」 です。
REST APIは「状態を持たない設計にするべき」と説明されることがあります。
しかし、初心者にとっては少し分かりにくい表現です。
「状態を持たない」とはどういう意味なのか。
「ログイン状態」はどうなるのか。
「セッションを使ってはいけない」という意味なのか。
「データベースに保存してはいけない」という意味なのか。
このあたりで混乱する人は多いです。
この記事では、REST APIにおける「状態を持たない」、つまりステートレスの意味を初心者向けに整理します。
- ステートレスとは何か
- 「状態を持たない」の状態とは何か
- ステートフルとステートレスの違い
- REST APIではなぜステートレスが重要なのか
- ステートレスだとサーバーを増やしやすい
- ステートレスは「ログインできない」という意味ではない
- Cookieやセッションはステートレスではないのか
- JWTを使えば完全にステートレスなのか
- ステートレスは「DBに保存しない」という意味ではない
- ステートレスなAPIの例
- ステートフルになりやすいAPIの例
- ステートレスと冪等性は別の話
- ステートレスとキャッシュの関係
- ステートレスにするための設計ポイント
- 実務では完全なステートレスだけが正解ではない
- 初心者向けの理解:レストランで例える
- ステートレスAPIのチェックリスト
- よくある誤解まとめ
- まとめ
ステートレスとは何か
ステートレスとは、簡単に言うと サーバーがクライアントごとの前回の状態を覚えていないこと です。
もう少し具体的に言うと、REST APIでは、1回ごとのリクエストがそれ単体で完結している必要があります。
たとえば、APIにリクエストを送るときは、そのリクエストの中に必要な情報を含めます。
GET /api/users/1
Authorization: Bearer xxxxx
このリクエストを見るだけで、サーバーは次のことを判断できます。
- どのユーザー情報を取得したいのか
- 認証済みのリクエストなのか
- 誰からのリクエストなのか
- 処理してよいリクエストなのか
つまり、サーバーが「前回この人はログインしていたはず」「前のリクエストでuser_idを受け取ったはず」と覚えている前提にしない、ということです。
「状態を持たない」の状態とは何か
ここでいう「状態」とは、主に クライアントごとの会話の途中経過 のことです。
たとえば、次のような情報です。
このユーザーはログイン済み
このユーザーは検索条件に「東京」を指定していた
このユーザーは前回2ページ目を見ていた
このユーザーは今、購入手続きの途中
このユーザーは直前に商品ID 100 を選んだ
このような情報をサーバーのメモリ上に保持して、次のリクエストで使う設計は「状態を持つ」設計です。
一方、ステートレスな設計では、次のリクエストに必要な情報は、そのリクエスト自身に含めます。
GET /api/products?keyword=東京&page=2
Authorization: Bearer xxxxx
このように、検索キーワードやページ番号、認証情報などをリクエストに含めることで、サーバーは過去のリクエストを覚えていなくても処理できます。
ステートフルとステートレスの違い
ステートレスを理解するには、反対の「ステートフル」と比較すると分かりやすいです。
ステートフルな例
ステートフルな設計では、サーバーがクライアントごとの状態を覚えます。
1回目のリクエスト:
「商品一覧を見たい。検索条件はノートPC」
サーバー:
「このユーザーの検索条件はノートPCだな」と覚える
2回目のリクエスト:
「次のページを見たい」
サーバー:
「前回の検索条件はノートPCだったから、ノートPCの2ページ目を返そう」
この設計では、2回目のリクエストだけを見ると、何の2ページ目なのか分かりません。
サーバーが前回の状態を覚えている必要があります。
ステートレスな例
ステートレスな設計では、必要な情報を毎回リクエストに含めます。
1回目のリクエスト:
GET /api/products?keyword=notebook&page=1
2回目のリクエスト:
GET /api/products?keyword=notebook&page=2
この場合、2回目のリクエストだけを見ても、サーバーは処理できます。
「notebookで検索した商品の2ページ目が欲しい」と分かるからです。
これが、REST APIにおけるステートレスの基本です。
REST APIではなぜステートレスが重要なのか
REST APIでステートレスが重視される理由は、システムを扱いやすくするためです。
特に、WebサービスやスマートフォンアプリのAPIでは、多くのクライアントから大量のリクエストが届きます。
そのとき、サーバーがクライアントごとの状態を持っていると、構成が複雑になります。
一方、ステートレスにすると、次のようなメリットがあります。
- サーバーを増やしやすい
- 負荷分散しやすい
- 障害に強くしやすい
- キャッシュしやすい
- APIの挙動を理解しやすい
- テストしやすい
- リクエスト単位でログを追いやすい
特に大きいのは、どのサーバーがリクエストを受けても処理できる ことです。
ステートレスだとサーバーを増やしやすい
たとえば、APIサーバーが3台あるとします。
クライアント
↓
ロードバランサー
↓
APIサーバーA
APIサーバーB
APIサーバーC
ステートレスな設計であれば、どのAPIサーバーにリクエストが届いても同じように処理できます。
なぜなら、必要な情報はリクエストに含まれているからです。
一方、サーバーAだけが特定ユーザーの状態を覚えている場合、次のリクエストがサーバーBに届くと困ります。
1回目: サーバーAが状態を覚える
2回目: サーバーBにリクエストが届く
サーバーB: 「前回の状態が分からない」
この場合、同じユーザーのリクエストを同じサーバーに振り分ける必要が出ます。
これは構成を複雑にします。
ステートレスにしておけば、サーバーを増やしたり、入れ替えたりしやすくなります。
ステートレスは「ログインできない」という意味ではない
初心者が特に混乱しやすいのが、ログインとの関係です。
「サーバーが状態を持たないなら、ログイン状態はどうやって管理するの?」と思うかもしれません。
結論から言うと、ステートレスでもログインはできます。
ただし、サーバーが「この人はログイン済み」とメモリ上で覚えておくのではなく、リクエストごとに認証情報を送ります。
代表的なのが、トークン認証です。
GET /api/me
Authorization: Bearer xxxxx
サーバーは、このトークンを見て「誰からのリクエストか」「有効な認証情報か」を判断します。
つまり、ログイン状態をサーバーの会話履歴として覚えるのではなく、毎回のリクエストで認証情報を確認するわけです。
Cookieやセッションはステートレスではないのか
REST APIの話でよく出る疑問が、Cookieやセッションとの関係です。
Webアプリでは、ログイン後にセッションIDをCookieに保存し、サーバー側でセッション情報を管理することがあります。
Cookie: session_id=abc123
この場合、サーバー側には次のようなセッション情報があります。
session_id=abc123 は user_id=1 のログイン状態
これは、厳密にはサーバー側が状態を持っている設計です。
そのため、純粋な意味ではステートレスとは言いにくいです。
ただし、実務ではCookieセッションを使ったWebアプリも多く存在します。
重要なのは、「RESTっぽいかどうか」だけではなく、システムの要件に合っているかです。
APIとしてステートレス性を重視するなら、JWTやアクセストークンなどを使って、リクエストごとに認証情報を渡す設計がよく使われます。
JWTを使えば完全にステートレスなのか
JWTは、ステートレスな認証でよく使われる仕組みです。
JWTには、ユーザー情報や有効期限などを含めることができます。
Authorization: Bearer <JWT>
サーバーはJWTの署名を検証することで、トークンが正しいか確認できます。
この場合、サーバー側にセッション情報を保存しなくても認証できます。
そのため、JWTはステートレスな認証方式として扱われることが多いです。
ただし、JWTにも注意点があります。
- トークンを盗まれると危険
- 有効期限の設計が重要
- 強制ログアウトが難しくなる場合がある
- トークン無効化リストを持つとステートフル寄りになる
- 情報を詰め込みすぎると扱いづらい
JWTを使ったから自動的に良い設計になるわけではありません。
ステートレス性とセキュリティ、運用性のバランスを考える必要があります。
ステートレスは「DBに保存しない」という意味ではない
もう一つ大きな誤解があります。
それは、ステートレスを「データベースに状態を保存してはいけない」という意味だと考えてしまうことです。
これは違います。
REST APIのステートレスは、サーバーがクライアントとの会話状態を保持しない という意味です。
データベースにデータを保存すること自体は問題ありません。
たとえば、次のようなデータは普通に保存します。
- ユーザー情報
- 商品情報
- 注文情報
- 投稿データ
- 予約情報
- 決済履歴
- 設定情報
これらはアプリケーションの正式なデータです。
ステートレスで問題になるのは、次のような「一時的な会話の途中経過」をサーバー側だけで覚えることです。
このユーザーは前回どの検索条件を使ったか
このユーザーは今どの画面の途中か
このユーザーの次の処理は何か
もちろん、ショッピングカートや申込途中データのように、業務上保存すべき状態もあります。
その場合は、サーバーのメモリではなく、データベースなどに明示的なリソースとして保存する設計にします。
ステートレスなAPIの例
ステートレスなAPIの例を見てみます。
ユーザー情報の取得
GET /api/users/1
Authorization: Bearer xxxxx
このリクエストには、必要な情報が含まれています。
- 取得したいユーザーID
- 認証情報
サーバーは前回のリクエストを覚えていなくても処理できます。
商品検索
GET /api/products?keyword=keyboard&category=pc&page=2
Authorization: Bearer xxxxx
このリクエストには、検索条件が含まれています。
- keyword
- category
- page
- 認証情報
サーバーが「前回の検索条件」を覚えている必要はありません。
注文作成
POST /api/orders
Authorization: Bearer xxxxx
Content-Type: application/json
{
"items": [
{
"product_id": 10,
"quantity": 2
},
{
"product_id": 20,
"quantity": 1
}
],
"shipping_address_id": 5,
"payment_method_id": 3
}
注文作成に必要な情報がリクエストボディに含まれています。
サーバーは、前回のリクエストを参照しなくても注文処理を開始できます。
ステートフルになりやすいAPIの例
次のようなAPIは、ステートフルになりやすいです。
POST /api/search
{
"keyword": "keyboard"
}
その後に、次のようなリクエストを送るとします。
GET /api/search/next
この場合、/api/search/next だけを見ても、何の検索結果の次ページなのか分かりません。
サーバーが「このユーザーの前回の検索条件はkeyboardだった」と覚えている必要があります。
ステートレスにするなら、次のようにします。
GET /api/products?keyword=keyboard&page=2
このように、必要な検索条件とページ番号を毎回渡す方が分かりやすいです。
ステートレスと冪等性は別の話
REST APIを学んでいると、「ステートレス」と一緒に「冪等性」という言葉も出てくることがあります。
この2つは関係していますが、同じ意味ではありません。
ステートレスは、サーバーがクライアントごとの前回の状態を覚えないことです。
一方、冪等性は、同じリクエストを何度実行しても結果が同じになる性質です。
たとえば、次のPUTリクエストは冪等にしやすいです。
PUT /api/users/1
Content-Type: application/json
{
"name": "Taro"
}
同じ内容で何度更新しても、最終的な名前はTaroです。
一方、POSTで注文を作成するAPIは、同じリクエストを複数回送ると注文が複数作られる可能性があります。
POST /api/orders
これは冪等ではない場合があります。
ステートレスと冪等性は混同しやすいですが、別の概念として理解しましょう。
ステートレスとキャッシュの関係
ステートレスなAPIは、キャッシュしやすいというメリットがあります。
たとえば、次のようなリクエストは、URLを見るだけで取得対象が分かります。
GET /api/products?category=book&page=1
このようなAPIは、レスポンスをキャッシュしやすくなります。
一方、サーバー側の状態に依存して結果が変わるAPIは、キャッシュが難しくなります。
GET /api/search/next
このURLだけでは、何の検索結果なのか分かりません。
キャッシュキーとして扱いづらくなります。
もちろん、認証ユーザーごとに結果が変わるAPIでは、キャッシュ設計に注意が必要です。
しかし、リクエスト単体で意味が分かる設計にしておくことは、キャッシュやデバッグの面でも有利です。
ステートレスにするための設計ポイント
REST APIをステートレスに近づけるには、次の点を意識するとよいです。
1. 必要な情報をリクエストに含める
サーバーが前回のリクエストを覚えていなくても処理できるようにします。
GET /api/articles?tag=api&page=3&sort=latest
検索条件、ページ番号、並び順などはリクエストに含めます。
2. 認証情報を毎回送る
APIでは、リクエストごとに認証情報を送る設計が一般的です。
Authorization: Bearer xxxxx
サーバーは毎回この情報を確認して処理します。
3. URLやHTTPメソッドで操作対象を明確にする
何を操作するのかを、URLやHTTPメソッドから分かるようにします。
GET /api/users/1
PATCH /api/users/1
DELETE /api/users/1
このように、リクエスト単体で意味が分かる設計にします。
4. 「次へ」「前へ」だけのAPIを避ける
ステートフルになりやすいAPIの例が、「次へ」だけを指定するAPIです。
GET /api/next
これでは、何の次なのか分かりません。
代わりに、ページ番号やカーソルを明示します。
GET /api/products?page=2
または、カーソルベースのページネーションなら次のようにします。
GET /api/products?cursor=eyJpZCI6MTAwfQ
カーソルを使う場合も、リクエストに必要な情報を含めているので、ステートレスな設計にしやすいです。
5. 一時状態をサーバーメモリに置かない
ユーザーごとの一時状態をAPIサーバーのメモリに保存すると、スケールしにくくなります。
避けたい例です。
APIサーバーのメモリに、
user_idごとの検索条件や処理途中状態を保存する
必要な状態であれば、データベースやRedisなどに明示的に保存し、APIリソースとして扱う方が管理しやすいです。
実務では完全なステートレスだけが正解ではない
ここまでステートレスの重要性を説明しましたが、実務では「完全にステートレスでなければならない」と考えすぎる必要はありません。
たとえば、次のようなケースでは、状態管理が必要になることがあります。
- ログインセッション
- ショッピングカート
- 決済フロー
- 申込途中の入力内容
- OAuthの認可フロー
- ワンタイムトークン
- CSRF対策
- レート制限
- WebSocket接続
重要なのは、状態を持つ場合でも、どこに、何のために、どの期間、どの粒度で持つのか を明確にすることです。
APIサーバーのメモリに何となく持つのではなく、データベース、Redis、トークン、Cookieなど、目的に合った場所で管理します。
初心者向けの理解:レストランで例える
ステートレスをレストランで例えてみます。
ステートフルな店員
ステートフルな店員は、前回の会話を覚えています。
客: ハンバーグをお願いします
店員: 分かりました
客: やっぱり大盛りで
店員: さっきのハンバーグを大盛りにしますね
この場合、店員は前回の注文を覚えている必要があります。
ステートレスな注文票
ステートレスな仕組みでは、毎回注文票に必要な情報を書きます。
注文票:
メニュー: ハンバーグ
サイズ: 大盛り
ソース: デミグラス
店員が前回の会話を覚えていなくても、注文票を見れば処理できます。
REST APIのリクエストもこれに近いです。
サーバーが前回の会話を覚えていなくても、リクエストを見れば処理できる状態にするのがステートレスです。
ステートレスAPIのチェックリスト
REST APIを設計するときは、次のような観点で確認するとよいです。
□ そのリクエスト単体で処理内容が分かるか
□ 前回のリクエストに依存していないか
□ 検索条件やページ番号をリクエストに含めているか
□ 認証情報をリクエストごとに送っているか
□ APIサーバーのメモリにユーザーごとの状態を保存していないか
□ どのサーバーに届いても同じように処理できるか
□ URLとHTTPメソッドから操作対象が分かるか
□ 必要な状態はDBやRedisなどに明示的に保存しているか
□ 「次へ」「前へ」だけのような曖昧なAPIになっていないか
このチェックリストに多く当てはまれば、ステートレスなAPIに近づいています。
よくある誤解まとめ
ステートレスはログインできないという意味?
違います。
ログインはできます。
ただし、リクエストごとにトークンや認証情報を送って、毎回認証を確認する設計にします。
ステートレスはDBに保存しないという意味?
違います。
ユーザー情報、注文情報、投稿データなど、アプリケーションの正式なデータはDBに保存します。
ステートレスが問題にするのは、サーバーがクライアントごとの会話状態を覚えることです。
セッションを使ったらREST APIではない?
厳密にはステートレス性は弱くなります。
ただし、実務ではCookieセッションを使うWebアプリもあります。
APIの用途、セキュリティ要件、運用性を見て判断する必要があります。
JWTを使えば常に正解?
違います。
JWTはステートレス認証に使いやすいですが、トークン管理や失効、漏洩対策を考える必要があります。
場合によっては、セッション方式の方が扱いやすいこともあります。
まとめ
REST APIにおける「状態を持たない」とは、サーバーがクライアントごとの前回の状態を覚えなくても、各リクエストを処理できるようにすること です。
ポイントを整理すると、次の通りです。
ステートレスの要点
・リクエスト単体で処理に必要な情報を持つ
・サーバーは前回のリクエストを覚えている前提にしない
・認証情報はリクエストごとに送る
・検索条件やページ番号もリクエストに含める
・DBにデータを保存すること自体は問題ない
・サーバーのメモリにユーザーごとの会話状態を持つとステートフルになる
・ステートレスにすると負荷分散やスケールがしやすい
REST APIでステートレスが重視されるのは、きれいな設計に見えるからだけではありません。
サーバーを増やしやすくし、障害に強くし、テストやデバッグをしやすくするためです。
初心者のうちは、まず次のように考えると分かりやすいです。
そのリクエストだけを見て、サーバーが処理できるか?
この問いに「はい」と答えられるAPIは、ステートレスなREST APIに近い設計です。

大阪のエンジニアが書いているブログ。


コメント