- はじめに — 2.12の次が2.14である理由から
- 高速バッチパブリッシュ — async publishの後継
- 繰り返しスケジュールとサンプリング — cronがサーバーの中へ
- WorkQueue・Interestソーシングがもう途切れない
- コンシューマーリセットAPI
- 運用者の視点で本当に重要な3つ
- APIレベルで見る機能ゲーティングと、3つのリリーストレイン
- で、いつ上げて、いつ待つか
- おわりに
- 参考資料
はじめに — 2.12の次が2.14である理由から
NATS Server 2.14.0は2026年4月30日にリリースされました。直前のマイナーリリースである2.12.0が2025年9月22日だったので、約7か月ぶりです。NATSチームは2.12リリースの記事で6か月リリースサイクルへの移行を明らかにしていましたが、2.14リリースの記事は今回1か月ほど遅れた理由を「AIによるセキュリティレビューと開示対応活動が増えたため」と書いています。AIが生み出すセキュリティ報告がオープンソースのメンテナーのリリーススケジュールを押す時代だという、2026年の風景がリリースノートから読み取れます。
そしてバージョン番号。リリースノートの最初の行に「2.13.xバージョンはスキップされた(the 2.13.x version was skipped)」と明記されています。理由はリリースノートにも、ブログにも、アップグレードガイドにもありません。gitの履歴を見ると、2.12.0リリースの翌日である2025年9月23日にmainブランチが直ちにv2.14.0-devへ上がっているので、あとから番号を変えたのではなく、サイクルの開始時点から計画されたスキップでした。後述しますが、JetStream APIレベル番号とサーバーのマイナーバージョンが再び一致するようになったという観察はできますが、これは筆者の推測であって公式の説明ではありません。
本稿はハイライトの羅列ではなく、リリースノートとアップグレードガイド、設計文書(ADR)、サーバーソースを直接確認して「実際に何をして、何をせず、運用者が何に気をつけるべきか」を整理します。NATS自体が初めてなら、先に分散メッセージング 2026 — Kafka 3.9 / NATS / Redpanda / Pulsar / RabbitMQ 4 / WarpStream 徹底比較を読むとよいでしょう。
高速バッチパブリッシュ — async publishの後継
2.14の代表機能です。背景から整理すると、2.12が導入したアトミックバッチパブリッシュ(atomic batch publish)は、N件のメッセージをステージングしておき、一貫性チェックをすべて通過して初めてバッチ全体をコミットするall-or-nothing方式でした。KVストアで住所を構成する5個のキーを一括更新するような問題にはぴったり合いますが、ステージングのためバッチサイズに実質的な上限があります(ADR-50はアトミックバッチの1,000件制限に言及しています)。
2.14の高速バッチは目的が異なります。原子性ではなく、スループットとフロー制御が目標です。
アトミックバッチ (2.12) 高速バッチ (2.14)
目的 all-or-nothingの正確性 高速インジェスト + フロー制御
保存方式 ステージング後に一括コミット 到着次第すぐ保存
一貫性チェック バッチ全体単位 メッセージ単位でインライン
サイズ上限 あり (ADR基準1,000件) 事実上無制限
失敗時 バッチ全体を拒否 gap:fail — バッチ中断 / gap:ok — ギャップ報告のうえ継続
リーダー交代 バッチ破棄 gap:okモードなら生存
設計の核心は、バッチが開いている間維持されるコントロールチャネルです。クライアントはメッセージごとにackを待たず、サーバーがおよそ10件に1回の割合でフロー制御ack(BatchFlowAck)を送ります。フロー速度はサーバーが決めます — ADRによれば、クライアントが最大フローを要求してもサーバーは低い値(例えば1)から始め、余裕があればおよそ2倍ずつ上げ、負荷を検知すると半分に減らします。判断の根拠は、同時実行中の高速パブリッシャー数、平均メッセージサイズ、まだ永続化されていないインフライト量といったサーバー内部の指標です。
ギャップ(欠落)の扱いは2つのモードから選びます。failモードはギャップを検知した瞬間にバッチを中断し、順序保証が必要な場合(例: オブジェクトストアのファイルチャンク)に適しています。okモードはギャップをBatchFlowGapメッセージで報告するだけで処理を続け、一部欠落を許容できる高頻度メトリクスのパブリッシャーに適しています。ADRはこの設計の最終目標をはっきり書いています — 既存クライアントのasync publishをこれで置き換えることです。
性能の主張については正直である必要があります。公式ブログは「設定次第でasync publishに対しほぼ2倍までスループットが出ることがある」と書いていますが、これはベンダーの自己申告であり、測定条件(メッセージサイズ、レプリケーションレベル、ハードウェア、クライアント数)は公開されていません。再現可能なベンチマーク数値は現時点で公開されていません。ただし定性的な動機はうなずけます — フロー制御の欠如で壊れやすかった既存のasync publishと異なり、オブジェクトストアへのアップロードが2つ同時に走っても、サーバーがパブリッシャーの速度を直接調整するので、同時パブリッシャーが数百に及んでもそれぞれがフロー制御を受けるというのがブログの主張です(これも自己申告です)。
クライアント対応状況も現実的に見る必要があります。この機能を使うにはストリームでAllowBatchPublishオプションを有効にし、対応するクライアントが必要ですが、執筆時点で公式実装はGo拡張ライブラリのorbit.goのjetstreamext v0.3.0(2026-04-21、FastPublisher)が先行しています。そして2週間後にv0.3.1がFastPublisherのストール・タイムアウト・リプライプレフィックスのバグを修正しました。コアのnats.goにはv1.52.0でストリーム設定フィールドだけが入りました。最初の実装がリリース直後にバグ修正を経た、まだ若い機能だということです。プロダクションの中核パスに入れる前に、自分のワークロードで検証するのが妥当です。
繰り返しスケジュールとサンプリング — cronがサーバーの中へ
2.12はNats-Schedule-TTLヘッダーで「あとで一度だけ配達されるメッセージ」(delayed message)を導入しました。2.14はこれを繰り返しスケジュールへ拡張します。メッセージにNats-Schedule: @every 5mのような間隔や@hourly、あるいはcron式を付けておくと、サーバーがそのスケジュール通りに対象サブジェクトへメッセージを作り続けます。
nats pub -J 'schedules.orders.hourly' \
-H "Nats-Schedule: @hourly" \
-H "Nats-Schedule-TTL: 5m" \
-H "Nats-Schedule-Target: orders" \
'body'
クライアント側にタイマーを回す専用パブリッシャーを常駐させる必要がなくなるのが要点です。派生機能も2つ加わりました。サブジェクトサンプリングはNats-Schedule-Sourceヘッダーで「スケジュールが発火するたびにソースサブジェクトの最後のメッセージを読み、ターゲットへ発行」します — エッジで秒単位に流れ込むセンサー値を5分に1回だけクラウドへ上げるサーバーサイドのダウンサンプリングが代表的なユースケースです(ソースにメッセージがなければ、スケジュールメッセージ自身の本文がフォールバックとして発行されます)。スケジュールロールアップはNats-Schedule-Rollupヘッダーで発行時点にそのサブジェクトをロールアップします。
ADR-51で確認した、ドキュメントを読まないと踏む制約です。
- スケジュール1つにつき固有のサブジェクトが必要です。同じターゲットへ向かう遅延メッセージを複数持たせたい場合は、
orders.schedule.UUIDのようにスケジュールメッセージのサブジェクトを一意にし、Nats-Schedule-Targetでまとめます。 @everyの最小間隔は1秒です。それより短いと拒否されます。- cronは秒フィールドを含む6フィールド形式で、デフォルトのタイムゾーンはUTCです。
Nats-Schedule-Time-ZoneヘッダーでIANAタイムゾーン(Asia/Seoulなど)を指定できますが、サーバーがホストのtzdataで名前を解決するため、cronスケジュールを評価するすべてのサーバーにtzdataがインストールされ、最新である必要があるという運用要件が伴います。固定オフセット(+02:00)は受け付けません。 - ADRはDST切り替え時刻にかかるcronを推奨していません — 時計が前に進むとその回がスキップされ得る、後ろに戻ると二重実行され得ると明記しています。
- サーバーが長時間停止していて復旧すると、過去に過ぎたスケジュールは即座に発火します。1か月前に予約したメッセージが復旧直後に届くのを避けたい場合、スケジュールメッセージに
Nats-TTLを付けて期限切れにするのがADRの案内する防御策です。 - スケジュールを使うストリームにDiscard NewポリシーはサポートされないとADRが明記しており、2.14.2はカウンターストリームとスケジュールに対する構成制約の検証を強化しました。
いつ使うべきでないか — これは分散cronスケジューラの代替ではありません。実行履歴の追跡、失敗時の再試行ポリシー、重複防止といったジョブスケジューラの責務は依然としてコンシューマー側にあり、サーバーがしてくれるのは「その時刻にメッセージを作ってストリームへ入れる」ところまでです。逆に、「接続を保ったままタイマーだけ回すサイドカー」をなくす用途にはぴったり合います。
WorkQueue・Interestソーシングがもう途切れない
地味な名前の割に実質的な整合性の修正です。2.14まで、ストリームのミラー・ソースは内部的にエフェメラル(ephemeral)コンシューマーで非同期レプリケーションをしていました。問題はソーシング対象がWorkQueueまたはInterest保持ポリシーのストリームである場合です — 例えば、リーフノードがInterestストリームをソーシングしている最中に1週間ダウンすると、その間にinterestが消えたものとして扱われデータが自動削除され、リーフが復旧してもその区間はレプリケートされません。
2.14はWorkQueue・Interestストリームをソーシング・ミラーリングする際、自動的に永続(durable)コンシューマーへ切り替えます。新しいackポリシーAckFlowControlはフロー制御に基づいて永続化後に確認応答を行い、このコンシューマーはコンシューマー一覧に表示され、ソースのドメイン・アカウント・ストリームのメタデータを帯び、接続が切れても状態を保持します。セキュリティが重要な構成では、相手側がコンシューマー設定に触れられないよう、あらかじめ作成したコンシューマーを持ち込む(bring your own consumer)方式もサポートされています。
アップグレード中に注意すべき点が1つあります。混在バージョンのクラスタでは、アップグレード済みのサーバーが新方式のソーシングコンシューマー作成を試み、旧バージョンのサーバーがjson: unknown field "sourcing"という警告をログに残すことがあります。ガイドによれば自動的に旧方式へリトライするため、アップグレード全体が終われば消える一時的なログです。ダウングレードの方がより痛みを伴います — 2.12へ下げるとAckFlowControlコンシューマーはオフラインとしてマークされ、2.14へ戻すまで使えません。
コンシューマーリセットAPI
運用していると「このコンシューマーをシーケンスNからやり直したい」という瞬間が訪れます。これまではコンシューマーを削除し、開始シーケンスを指定して作り直す方法しかなく、その過程で名前・購読者・ACLに絡んだものが一緒に揺らいでいました。2.14は$JS.API.CONSUMER.RESET.stream.consumerAPIで、コンシューマーを削除せずにackフロアや任意のシーケンスへ配達状態をリセットできるようにしました。リセット後の状態は「そのシーケンスでdeleteしてrecreateしたのと同等」だとガイドは定義しています。
運用者の視点で本当に重要な3つ
機能一覧よりこの節の方がアップグレード判断にとって重要です。3つともアップグレードガイドに明記された挙動変化です。
第一に、filestore I/Oエラーが今やストリームを凍結させます。 以前のバージョンは一部のファイルシステムI/Oエラーをきちんと処理できず、ストリームとサーバーはそのまま動き続けていました。2.14からはエラーが表面化します — 影響を受けたストリームは凍結(freeze)して先に進まなくなり、ログにエラーを残し、ヘルスチェックがunhealthyを報告します。同じサーバー上の他のストリームは影響を受けず、レプリケーションされたストリームなら他のレプリカが透過的に引き継ぎます。ただし凍結したサーバー自体は再起動しないと復旧しません。静かに腐っていくよりは明らかにましですが、監視すべき新しい運用条件が生まれたということです — healthzの失敗メッセージでwrite errorを監視対象に加えてください。
第二に、Raftの過負荷保護。 これまでは、Raftログにエントリがコミット・適用の速度より速く積み上がると、メモリとディスクが際限なく増え得ました。2.14はこの状態を認識してリソース使用量を制限し、遅れているリーダーは自発的に退いてより健全なピアへ渡します。ガイドは限界も明確に書いています — ピアの過半数が同様に過負荷なら、システムは性能劣化状態にとどまり、この保護は一時的な過負荷向けの安全網であって、容量不足の代替にはならないと。この一文がリリース文書に入っていること自体が、このプロジェクトのドキュメントの美徳です。
第三に、2.15前に片付けておく宿題 — ACKサブジェクトフォーマットの移行。 2.14はコンシューマーの確認応答・フロー制御リプライサブジェクトのv2フォーマット(ドメイン・アカウントハッシュを含む)を並行してサポートし始めました。
v1: $JS.ACK.<stream>.<consumer>.<delivered>.<sseq>.<cseq>.<ts>.<pending>
v2: $JS.ACK.<domain>.<acct hash>.<stream>.<consumer>.<delivered>.<sseq>.<cseq>.<ts>.<pending>
2.14のデフォルトは依然v1ですが、2.15でデフォルトがv2に変わります。アカウントのimport/exportやサブジェクト権限にストリーム名まで埋め込んだACK・FCサブジェクトを使っているなら、2.15前にACLを更新する必要があるとガイドは明記しています(catch-allワイルドカードを使っている場合や、単一アカウントでのみJetStreamを使っている場合は該当しません)。事前にテストできるよう2.14でサーバー設定にfeature_flagsフィールドが追加され、ここでjs_ack_fc_v2を試せます。ただしこのフィールドを設定したまま2.12へダウングレードすると、旧バージョンがフィールドを認識しないため、下げる前に消しておく必要があります。
このほか静かに役立つ変更として、info・list系の照会APIリクエストが作成・更新・削除リクエストとは別のキューに入るようになり優先度が下がり(ダッシュボードのポーリングが運用作業を押しのける状況が緩和されます)、レプリケーションされたストリームの状態スナップショットがストリーム処理を止めずに非同期で記録されるようになりました — 内部削除(interior delete)が多いストリームのテール遅延に特に効果があるとされていますが、具体的な数値は公開されていません。
APIレベルで見る機能ゲーティングと、3つのリリーストレイン
2.11以降、NATSはJetStream機能をAPIレベルでゲーティングしています。サーバーソース(server/jetstream_versioning.go)で直接確認した値として、2.11がレベル1、2.12.0がレベル2、2.14.0がレベル4です。ではレベル3はどこへ行ったのか — 興味深いことに、メンテナンストレインである2.12.5(2026年3月)がレベル3を使っています。ストリームバックアップのwindow_sizeパラメータのような小さなAPI追加がパッチトレインに入り、レベルを1つ消費したのです。結果として2.13をスキップしたおかげで「マイナーバージョン − 10 = APIレベル」が2.14で再び一致するようになりましたが、繰り返しになりますが、これがスキップの理由だという公式説明はありません。
このレベルが実務で持つ意味はダウングレードの安全性です。上位レベルの機能を使うストリーム・コンシューマーは、旧バージョンのサーバーで壊れる代わりにオフラインとしてマークされ(2.12のoffline assets)、クライアントはNats-Required-Api-Levelヘッダーで要求レベルを明示できます。
リリーストレインの運用も注目に値します。GitHubのリリース履歴を見ると、2.14.0が出たあとも2.12.xはパッチを受け続けており、同じ日に並んでリリースされています — 6月2日に2.12.10と2.14.2が、6月29日に2.12.12と2.14.3が一緒に出ました。一方2.11.xは2.14.0リリース直前の4月27日の2.11.17で止まっています。つまり観察されるパターンは「現行 + 直前」の2トレインを同時にメンテナンスすることですが、公式のサポート期間ポリシー文書は見つからなかったので、これは履歴から読み取れるパターンであって保証ではありません。
で、いつ上げて、いつ待つか
すぐ上げる理由がある場合 — WorkQueue・Interestストリームをリーフノードでソーシングするトポロジー(整合性修正が実質的です)、コンシューマーリセットが必要な運用パターン、filestore I/Oエラーの早期表面化が歓迎される環境(ストレージが心もとないエッジ)、そしてサーバー内蔵のスケジュール・ダウンサンプリングがサイドカーを1つ消してくれるIoT・エッジ配備。
急ぐ理由がない場合 — 高速バッチが目的なら、クライアントのエコシステムがまだorbit.go(Go)中心で、最初の実装がバグ修正を経たばかりであることを踏まえ、自分のワークロードでベンチマークせずにコアパスへ入れない方がよいでしょう。2.12.xトレインが依然として同じ日付でパッチを受けているので、新機能が不要なら2.12.12にとどまるのも現時点では擁護できる選択です。ただしどちらの場合でも、ACKサブジェクトACLをきめ細かく使うマルチテナント環境なら、2.15でデフォルトが変わる前にjs_ack_fc_v2への移行準備を今から始めるのが正しいでしょう。
付け加えると、同じ時期にメッセージングエコシステムの別の軸では、KafkaがKIP-1150ディスクレストピックでストレージ層そのものを再設計しています。Kafkaはブローカーのディスクをオブジェクトストレージへ押し出す方向へ、NATSはサーバーがパブリッシャーのフローを直接調整する方向へ — スループットとコストの問題を解く進み方が枝分かれしていくのを並べて見る面白さがあります。両システムのポジショニングの違いはメッセージングシステム総合ガイドで扱いました。
おわりに
まとめると、2.14は華やかなリリースというより「JetStreamを大量インジェストと無人運用の方向へ一段押し進める」リリースです。高速バッチはasync publishの構造的弱点(フロー制御の欠如)をサーバー主導の調整で解き、スケジュールはタイマーサイドカーをサーバーへ吸収し、WorkQueue・Interestソーシングは静かにデータを失っていた穴を塞ぎました。その代償として、運用者には新しい監視対象(ストリームのfreeze)と移行の宿題(ACK v2のACL)が生まれました。
性能の数値はまだベンダーの自己申告のみなので、導入判断はドキュメントの主張ではなく自分のワークロードの測定で行ってください。そしてこのリリースのドキュメント — 限界を明記したアップグレードガイド、DSTで二重実行され得ると書いたADR — は、その測定を始めるにはかなり良い出発点です。
参考資料
- NATS Server v2.14.0 リリースノート
- NATS 2.14 アップグレードガイド
- NATS Server 2.14 Release — 公式ブログ
- NATS Server 2.12 Release — 公式ブログ (6か月サイクルへの移行)
- ADR-50 — JetStream Batch Publishing (アトミックバッチ + 高速インジェスト)
- ADR-51 — JetStream Message Scheduler
- orbit.go jetstreamext リリース (FastPublisher)
- Kafka KIP-1150 ディスクレストピック分析 (関連記事)
현재 단락 (1/59)
NATS Server 2.14.0は[2026年4月30日にリリース](https://github.com/nats-io/nats-server/releases/tag/v2.14.0)されま...