Kafka

Kafka Schema Registryの互換性モードの選び方:BACKWARD / FORWARD / FULLを実務とCCDAK視点で整理

2026-04-19
NicheeLab編集部

スキーマ進化はKafka本番運用の要です。互換性モードの選択を誤ると、ロールアウト途中で消費者がデータを読めなくなります。特にCCDAKでは「どちらを先に更新するか」と互換性モードの対応関係が頻出ポイントです。

本稿では、公式ドキュメントの挙動に沿って、BACKWARD / FORWARD / FULLの本質、推移(Transitive)設定、デプロイ戦略との整合、よくある落とし穴をまとめます。最終章にREST API例と演習問題も付けています。

互換性モードの基礎と選択基準

互換性モードは、新しいスキーマを登録する際に「直前(あるいは履歴)のスキーマと比較して安全に読み書きできるか」をSchema Registryが検証する仕組みです。要点は、どちらの順番でロールアウトするかです。

BACKWARDは消費者(新スキーマ)→生産者(旧データ)を読み取れることを保証し、消費者先行の更新に向きます。FORWARDは消費者(旧スキーマ)→生産者(新データ)を読み取れることを保証し、生産者先行の更新に向きます。FULLは両方向を同時に満たし、混在期間が長い場合や双方向互換が必要なときに使います。

  • 消費者を先に更新する計画ならBACKWARD(あるいはBACKWARD_TRANSITIVE)
  • 生産者を先に更新する計画ならFORWARD(あるいはFORWARD_TRANSITIVE)
  • どちらも混在しうる、契約が厳密、長期ロールアウトならFULL(またはFULL_TRANSITIVE)
  • 互換性なし(NONE)は基本的に避ける。本番では短時間の例外対応に限定
モード保証される互換性ロールアウト指向代表的に安全な変更
BACKWARD新スキーマの消費者が旧データを読める消費者先行フィールド追加(デフォルト必須)、型の昇格(Avroのルール内)
FORWARD旧スキーマの消費者が新データを読める生産者先行フィールド削除(旧側でデフォルト補完可)、互換な型変換
FULLBACKWARDとFORWARDの両方双方向混在慎重な追加・削除・型変換(両方向でOKなもののみ)
NONE検証なしなしなし

ロールアウト方向と互換性モードの関係(概念図)

時間 -->

消費者先行(BACKWARD):

  Consumer v2 (new schema)
        ^             ^ 読める
        |             |
  Consumer v1   <-  Data by Producer v1/v2

生産者先行(FORWARD):

  Data by Producer v2 (new schema)  ->  Consumer v1 (old schema) 読める
                 ^ 生産者を先に切替

FULL(双方向):

  Producer v1/v2 混在 <-> Consumer v1/v2 混在
  どちらの組み合わせでも読めることを要求

推移(Transitive)と履歴互換の考え方

BACKWARDやFORWARDには、直前バージョンのみを比較する通常モードと、履歴上の全バージョンと比較する推移モード(_TRANSITIVE)が存在します。

長寿命トピックや多数のアプリが段階的にアップデートされる環境では、推移モードが安全側に働きます。短期で必ず全クライアントが追随できる前提なら通常モードでも現実的です。

  • BACKWARD_TRANSITIVE: 新スキーマは履歴の全ての旧データを読める必要がある
  • FORWARD_TRANSITIVE: 履歴の全ての旧スキーマが新データを読める必要がある
  • FULL_TRANSITIVE: 双方向で履歴全体と互換である必要があり、最も厳しい
  • 迷う場合はまずTRANSITIVEを検討。古いアプリが長期間残る組織では有効

スキーマ進化の安全/危険パターン(Avro/JSON Schema/Protobuf)

Schema RegistryはAvro、JSON Schema、Protobufをサポートしますが、互換性判定は各フォーマットの解決ルールに基づきます。以下は実務で安全側とされる代表例です(詳細は各公式仕様に依存)。

特にAvroではデフォルト値の有無が重要で、追加や削除の安全性を大きく左右します。Protobufではフィールド番号の再利用禁止、予約管理がポイントです。

  • Avro: フィールド追加はデフォルト値を付ければ概ねBACKWARDで安全。フィールド削除はFORWARD側で安全になることが多い。型昇格(int→longなど)は許容範囲が定義されている。
  • JSON Schema: optionalなプロパティ追加は概ね安全。必須化や厳格化は破壊的になりやすい。
  • Protobuf: 新規フィールド追加は通常安全(proto3はデフォルトでoptional)。フィールド番号の変更・再利用は禁止。名前の変更はワイヤ互換に影響しにくいが番号は厳守。
  • ENUMの削除や意味変更は注意。UNKNOWN相当の扱いを設計で用意する。
  • フィールドの必須化、意味の反転、IDセマンティクスの変更は互換性チェックを通っても論理的互換性を壊しうるためレビューが必要

デプロイ戦略と互換性モードの組み合わせ

ロールアウト順序と互換性モードの整合が取れていれば、長時間の混在期間でも事故を避けられます。逆に順序とモードが噛み合っていないと、途中で読めないデータが発生します。

サブジェクト命名戦略(TopicNameStrategy / RecordNameStrategy / TopicRecordNameStrategy)も進化計画に影響します。レコード再利用やスキーマの横展開があるならRecordNameStrategy系を検討し、影響範囲をサブジェクト単位で制御します。

  • 消費者先行: BACKWARD系。消費者が新スキーマで旧データを解釈できることが前提
  • 生産者先行: FORWARD系。旧消費者が新データを解釈できることが前提
  • 双方向/混在長期: FULL系。変更の自由度は下がるが運用は堅牢
  • サブジェクトは影響範囲最小化の単位。必要に応じてグローバル設定よりサブジェクト上書きを使う

設定と検証の手順(Schema Registry REST API)

互換性はグローバルとサブジェクト単位で設定できます。まずはグローバルを保守的に、例外的なサブジェクトのみ上書きするのが無難です。

本番適用前に必ず互換性APIで事前検証を行い、CIに組み込みます。

  • グローバル設定: PUT /config にcompatibility.levelを指定
  • サブジェクト上書き: PUT /config/{subject}
  • 事前検証: POST /compatibility/subjects/{subject}/versions/{version} に新スキーマを渡す
  • 登録: POST /subjects/{subject}/versions に新スキーマを渡す

互換性モード設定と事前検証の例(Avro, application/json)

## グローバル互換性をFULL_TRANSITIVEに設定
curl -s -X PUT \
  -H "Content-Type: application/json" \
  --data '{"compatibility": "FULL_TRANSITIVE"}' \
  http://localhost:8081/config

## サブジェクト単位で上書き(topic-valueをBACKWARDに)
curl -s -X PUT \
  -H "Content-Type: application/json" \
  --data '{"compatibility": "BACKWARD"}' \
  http://localhost:8081/config/my-topic-value

## 既存バージョン(latest)との互換性を事前チェック
NEW_SCHEMA='{
  "schema": "{\"type\":\"record\",\"name\":\"User\",\"fields\":[{\"name\":\"id\",\"type\":\"long\"},{\"name\":\"name\",\"type\":\"string\",\"default\":\"\"}]}"
}'

curl -s -X POST \
  -H "Content-Type: application/json" \
  --data "$NEW_SCHEMA" \
  http://localhost:8081/compatibility/subjects/my-topic-value/versions/latest

## 問題なければ登録
curl -s -X POST \
  -H "Content-Type: application/json" \
  --data "$NEW_SCHEMA" \
  http://localhost:8081/subjects/my-topic-value/versions

試験対策の要点とよくある落とし穴

CCDAKでは、互換性名称とロールアウト方向の取り違えが典型的なひっかけです。BACKWARDは「新が旧を読める」、FORWARDは「旧が新を読める」。この向きを体で覚えてください。

また、TRANSITIVEの有無、フィールドのデフォルト、Protobufのフィールド番号の扱いなども問われます。互換性チェックは直前または履歴全体との機械的な整合であり、意味論的な破壊は検出できない点も注意。

  • BACKWARD=消費者先行、FORWARD=生産者先行、FULL=両方向
  • TRANSITIVEは履歴全体と比較。長寿命トピックで有効
  • Avroの追加はデフォルト必須。Protobufは番号を変えない・再利用しない
  • NONEは原則避けるが、一時的な移行で短時間だけ使う現場もある。終了後は必ず元に戻す

問題で確認

CCDAK

問題 1

既存の消費者(旧スキーマ)は当面変更できません。一方で生産者を先にデプロイし、新しいフィールドを追加したい。どの互換性モードが適切ですか?

  1. FORWARD
  2. BACKWARD
  3. FULL
  4. NONE

正解: A

生産者先行のロールアウトでは、旧スキーマの消費者が新データを読めることを保証するFORWARDが適切。FULLでも要件を満たすが、問題文では旧消費者のみの読み取り保証が主眼のためFORWARDが最小要件に合致する。

よくある質問

BACKWARDとBACKWARD_TRANSITIVEの違いは?

前者は直前バージョンとの互換性を求め、後者は履歴上の全てのバージョンとの互換性を求めます。長期間にわたり古いデータが残る、または古い消費者が残存する場合はTRANSITIVEを選ぶと安全です.

JSON SchemaやProtobufでもAvroと同じ互換性ルールですか?

いいえ。互換性判定はフォーマット固有の解決ルールに基づきます。例えばProtobufはフィールド番号の再利用が禁止で、番号変更は破壊的です。JSON Schemaは必須化や制約強化が破壊的になりやすい。運用前に対象フォーマットの公式仕様を確認してください。

本番で一時的にNONEにして登録を通すのはアリ?

緊急対応として短時間のみという前提なら現場で行われることはありますが、強い推奨はできません。実施する場合は対象サブジェクト限定、直後にモード復元、CIでの事前互換性チェック強化、影響範囲レビューを徹底してください。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
Kafka

Kafka Topic と Partition の基礎: 分散とスケーラビリティの要

CCDAK 対策と実務の両立を意識し、Topic/Partition/Replica/Consumer Group の役...

Kafka

CCDAK 試験ガイド:出題範囲・配点・申込み・対策

Confluent Certified Developer for Apache Kafka (CCDAK) の出題範囲...

Kafka

Confluent Certified Administrator (CCAAK) 対策: 出題範囲・配点の考え方・運用観点の要点

CCAAKに向けて、試験領域の押さえどころを運用目線で整理。プロダクションで通用する設定・監視・セキュリティの実践知を、...

Kafka

Kafka の Replica と In-Sync Replicas を正しく設計する: 耐障害性と一貫性

レプリカとISRの仕組みを起点に、acks と min.insync.replicas、クリーン/アンクリーンリーダー選...

Kafka

Kafka の Offset とコミット: ポジション管理と at-least-once の基礎

CCDAK 対策と実務の両立を意識して、Kafka コンシューマのオフセット管理とコミット戦略を整理。at-least-...

Kafkaの記事一覧 (100件)
© 2026 NicheeLab All rights reserved.