ステートレス
Stateless
ステートレスは、ある要求を処理するために、サーバーがそのクライアントとの前の会話状態を覚えている必要がない設計です。対象とする境界を明確にして使います。DBにデータを保存しない、あるいは状態が世界のどこにもないという意味ではありません。
🐾 猫で例えると?
茶トラに顔をホールドされても、すやすや眠るアメショ。ここから「前のやり取りを引きずらず、毎回その場の情報で対応する」猫を想像してみましょう。例えばおやつを頼むたびに、名前と欲しい種類を伝えるなら、受け手は前回の会話を覚えていなくても対応できます。この、一回の要求に必要な情報を揃える点がステートレスに対応します。
💻 アプリ・Web開発における「ステートレス」とは?
たとえば取得要求に資源のIDと認証情報を含めれば、その要求を別のアプリサーバーが扱いやすくなります。商品や注文の現在の状態は、共有DBから取得しても構いません。要求の文脈と業務データを分けるのがポイントです。
毎回自己紹介から始めるような少し手間に見える方式ですが、現在のWebの根幹であるHTTP通信自体がこのステートレスな性質を持っています。API開発においても、RESTful APIの基本原則として非常に重要視される概念です。
⚠️ ステートレスの仕組みとメリット
特定のサーバー内の会話状態に依存しないと、要求を振り分けやすくなります。ただし台数を増やしても、共有DBの負荷、設定差、同時更新などは別の課題です。「どの要求も常に同じ結果」「台数追加だけで必ず解決」とは限りません。
ステートフルとの違い
逆に、サーバーがログイン状態などを記憶しておく方式を「ステートフル」と呼びます。ステートフルは便利ですが、特定のサーバーに依存しやすく、システム障害時の復旧が複雑になるというデメリットがあります。ステートレスでは、あるサーバーがダウンしても別のサーバーがそのまま処理を引き継げるため、システム全体の堅牢性が格段に上がります。
// /api/catsとaccessTokenを別途用意する前提の呼び出し例
async function loadCats(accessToken) {
const response = await fetch("/api/cats", {
headers: { Authorization: `Bearer ${accessToken}` }
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
}
// 実際の呼び出し側では失敗を捕捉して表示する Bearerトークンを送るだけでは、サーバーがステートレスかどうかは判断できません。トークンから保存済みセッションを検索する方式もあります。トークンの検証、期限、権限確認、HTTPSでの保護は、状態管理とは別に必要です。
🛠️ ステートレスを賢く使うためのポイント
ステートレスな設計は強力ですが、すべてのシステムに最適というわけではありません。要件に合わせて適切に使い分けることが重要です。
- トークンの性質を確認: JWTは一つの選択肢であり必須ではありません。署名付きのJWTでも内容が暗号化されているとは限らないため、秘密情報を安易に含めず、失効方法も決めます。
- リクエストの自己完結性を担保する: サーバーが過去のやり取りを推測する必要がないよう、一度の送信に過不足なくデータを含める。
- ステートフルな要件との分離: ショッピングカートやリアルタイム通信など、どうしても状態保持が必要な部分は専用のデータベースやキャッシュサーバーに切り出す。
マイペースなアメショに見立てると、前の要求に頼らず処理する姿を想像しやすくなります。ステートレスにする場合も、要求ごとに必要な情報を渡す設計や、共有データの保存先は必要です。アプリを増やすときは、保存先にも負荷が集中しないかを確認しましょう。