LESSON 30分

ストーリー

高橋アーキテクト
後方互換性の維持は大事だが、いつまでも古いバージョンを残すわけにはいかない

高橋アーキテクトがメンテナンスコストのグラフを見せた。 バージョンが増えるほど、コストが指数関数的に増加している。

高橋アーキテクト
古いバージョンの廃止には、計画と丁寧なコミュニケーションが必要だ。突然消すのは最悪の選択肢だ
あなた
どのくらいの期間、古いバージョンを残すものなんですか?
高橋アーキテクト
一般的には6ヶ月から12ヶ月の猶予期間を設ける。その間にクライアントに移行してもらう

廃止(Deprecation)のプロセス

4段階の廃止フロー

graph TD
    P1["Phase 1: 告知(Announcement)<br/>新バージョンリリースと同時に廃止予告"]
    P2["Phase 2: 移行期間(Migration Period)<br/>6〜12ヶ月の猶予期間"]
    P3["Phase 3: 警告強化(Warning Escalation)<br/>利用者に積極的に通知"]
    P4["Phase 4: 廃止実行(Sunset)<br/>古いバージョンを停止"]

    P1 --> P2 --> P3 --> P4

Phase 1: 告知

レスポンスヘッダーでの通知

// Sunset ヘッダー(RFC 8594)で廃止日を通知
HTTP/1.1 200 OK
Sunset: Sat, 31 Dec 2025 23:59:59 GMT
Deprecation: true
Link: <https://api.example.com/v2/docs>; rel="successor-version"

// クライアントはこのヘッダーを検出して警告を表示できる

APIドキュメントでの告知

// OpenAPI仕様書での非推奨マーク
// openapi.yaml
paths:
  /api/v1/users/{id}:
    get:
      deprecated: true  // 非推奨マーク
      summary: "[非推奨] ユーザー情報取得 - v2への移行をお願いします"
      description: |
        このエンドポイントは2025年12月31日に廃止されます。
        代替: GET /api/v2/users/{id}
        移行ガイド: https://docs.example.com/migration/v1-to-v2

Phase 2: 移行期間

マイグレーションガイドの提供

// マイグレーションガイドの内容
// 1. 変更点の一覧
// 2. 新旧APIの対応表
// 3. コード修正例
// 4. タイムライン

// 変更点の対応表の例
// | v1                  | v2                      | 変更内容 |
// |---------------------|-------------------------|---------|
// | GET /v1/users/:id   | GET /v2/users/:id       | name → firstName, lastName |
// | POST /v1/users      | POST /v2/users          | email が必須に |
// | DELETE /v1/users/:id| DELETE /v2/users/:id    | 変更なし |

// コード修正例
// Before (v1):
const user = await api.get('/v1/users/123');
console.log(user.name);  // "田中太郎"

// After (v2):
const user = await api.get('/v2/users/123');
console.log(`${user.lastName} ${user.firstName}`);  // "田中 太郎"

利用状況のモニタリング

// 非推奨APIの利用状況を追跡
function deprecatedApiMiddleware(version: string, sunset: string) {
  return (req: Request, res: Response, next: NextFunction) => {
    // ヘッダーを設定
    res.set('Sunset', sunset);
    res.set('Deprecation', 'true');

    // 利用状況をログに記録
    logger.warn({
      event: 'deprecated_api_usage',
      version,
      endpoint: `${req.method} ${req.path}`,
      clientId: req.headers['x-api-key'] || 'unknown',
      userAgent: req.headers['user-agent'],
    });

    next();
  };
}

// v1 ルーターに適用
v1Router.use(deprecatedApiMiddleware('v1', 'Sat, 31 Dec 2025 23:59:59 GMT'));

Phase 3: 警告強化

// 廃止日が近づいたら警告を強化

// 1. レスポンスボディにも警告を含める
{
  "data": { ... },
  "_warnings": [
    {
      "code": "DEPRECATED_API",
      "message": "このAPIは2025年12月31日に廃止されます。v2への移行をお願いします。",
      "migrationGuide": "https://docs.example.com/migration/v1-to-v2"
    }
  ]
}

// 2. メールやダッシュボードで個別通知
// 利用頻度の高いクライアントに直接連絡

// 3. レート制限を段階的に厳しくする
const V1_RATE_LIMITS = {
  '2025-07-01': { maxRequests: 1000 },   // 通常
  '2025-10-01': { maxRequests: 500 },    // 制限開始
  '2025-12-01': { maxRequests: 100 },    // 大幅制限
  '2025-12-31': { maxRequests: 0 },      // 停止
};

Phase 4: 廃止実行

// 完全に停止するのではなく、意味のあるエラーを返す
app.use('/api/v1', (req: Request, res: Response) => {
  res.status(410).json({
    error: {
      code: 'API_VERSION_SUNSET',
      message: 'API v1は2025年12月31日をもって廃止されました。',
      migrationGuide: 'https://docs.example.com/migration/v1-to-v2',
      newEndpoint: req.url.replace('/v1/', '/v2/'),
    }
  });
});

// 410 Gone: リソースが永久に利用不可

廃止ポリシーの策定

// APIのライフサイクルポリシー(ドキュメント化する)

// TaskFlow API ライフサイクルポリシー
// 1. 新バージョンのリリースと同時に、旧バージョンの廃止を告知する
// 2. 旧バージョンは最低12ヶ月間サポートする
// 3. 廃止6ヶ月前にリマインダーを送信する
// 4. 廃止1ヶ月前にレート制限を段階的に適用する
// 5. 廃止後は410 Goneを返し、移行ガイドを案内する
// 6. 同時にサポートするバージョンは最大2つまで

まとめ

フェーズ期間アクション
告知新バージョンリリース時Sunset ヘッダー、ドキュメント更新
移行期間6〜12ヶ月マイグレーションガイド提供、モニタリング
警告強化廃止3ヶ月前〜レスポンスに警告追加、個別通知
廃止実行廃止日410 Gone を返す

チェックリスト

  • 4段階の廃止フロー(告知→移行→警告→廃止)を理解した
  • Sunset ヘッダー(RFC 8594)の使い方を把握した
  • マイグレーションガイドに含めるべき内容を理解した
  • 廃止ポリシーの重要性を認識した

次のステップへ

API廃止とマイグレーション戦略を学びました。

次のセクションでは、API GatewayとBFF(Backend for Frontend)を学びます。 APIの前段に置くゲートウェイの役割と、クライアント別のBFF設計を理解しましょう。


推定読了時間: 30分