Development
18 min read
53 views

ダイナミックフェデレーション:ローカルGraphQLサブグラフを本番スーパグラフにトンネリング

IT
InstaTunnel Team
Published by our engineering team
ダイナミックフェデレーション:ローカルGraphQLサブグラフを本番スーパグラフにトンネリング

Quick answer

Dynamic Federation: Tunneling Local GraphQL Subgraphs: localhost tunnel answer

A localhost tunnel gives your local app a public HTTPS URL without opening router ports, which is useful for demos, QA, mobile testing, and provider callbacks.

How do I expose localhost without opening ports?

Use a reverse HTTPS tunnel. Your machine connects outbound to the tunnel service, and the public URL forwards requests back to your local app.

When should I use a localhost tunnel?

Use one for webhook testing, OAuth callbacks, client demos, QA previews, mobile device checks, and short-lived development reviews.

あなたは単一のGraphQLスキーマ変更をテストするために、ノートパソコン上で50のマイクロサービスを立ち上げる必要はありません。この記事では、サブグラフトンネルのアーキテクチャについて解説します。ローカルコードをシームレスにライブクラウドのスーパグラフに接続し、フルスタックをローカルで動かすことなく統合する方法を紹介します。


1. パラダイムシフト:モノリシックAPIからフェデレーテッドスーパグラフへ

GraphQLは、過剰取得や不足取得の標準解答として登場し、クライアントに単一の統合エンドポイントを提供します。組織の拡大に伴い、モノリシックなGraphQLサーバは進化のボトルネックとなりました。デプロイの衝突、スキーマの競合、単一サービスの不安定さが日常茶飯事となり、全体のグラフを停止させることもありました。

Apollo Federationはこれをアーキテクチャレベルで解決します。モノリシックスキーマをドメインごとに分解し、独立してデプロイ可能な*サブグラフ*にします。これらのSDLファイルを組み合わせて*スーパグラフ*を構築します。エッジには高性能なゲートウェイやルーターが配置され、クライアントのクエリを受け取り、クエリプランを作成し、並列リクエストを下位のサブグラフにディスパッチします。

フェデレーション2(現在の標準仕様)は、よりクリーンな共有所有モデル、型のマージの強化、新しい構成ヒントを導入し、エラーを早期に検出できるようになっています。サブグラフスキーマは、@linkディレクティブを適用して参加します。@key@shareable@provides@requires@interfaceObjectなどのフェデレーション専用ディレクティブは、サービス間のタイプの関係性をエンコードします。構成はこれらの契約を静的に検証し、ランタイムでルーターが消費するスーパグラフSDLアーティファクトを生成します。

Apollo Router Coreはこのアーキテクチャのリファレンスランタイムです。Rustで書かれ、正確性(GraphQLとフェデレーション仕様への厳格な準拠)、信頼性(予測可能なレイテンシ、メモリフットプリント、クラッシュフリー)、安全な実験(ランタイムの機能フラグと拡張フック)を設計原則としています。

フェデレーションは本番環境の組織的スケーリング問題を解決しましたが、開発ループには新たなボトルネックを生み出しました。


2. ローカル開発のボトルネック

10、30、50のサブグラフを持つフェデレーテッドアーキテクチャでは、開発者体験は急速に低下します。Inventoryサブグラフにフィールドを追加するには、その変更がクリーンに構成され、ProductsUsersInventoryを横断するクロスサービスクエリが正しく解決されることを確認する必要があります。

通常、次の3つの出口戦略があり、それぞれに実コストがあります。

フルスタックをローカルで実行。 Docker Composeを使っても、リソース枯渇は避けられません。CPUのスロットリング、OOMによる強制終了、ポートの競合がサービス数の増加とともに急増します。多くのエンジニアにとって、これを数サブグラフ以上で続けるのは現実的ではなくなります。

欠落サブグラフのモック。 開発者は自分のサービスだけをローカルで動かし、他の49のサブグラフをスタブ化できます。ただし、ドリフトのリスクがあります。モックはスナップショットであり、ステージングや本番は動的な対象です。実際のサービス間の結合ポイントに存在するバグは、CIの実行やマージ後にしか検出されません。

ステージング環境へのプッシュ。 これにより忠実度は保たれますが、フィードバックループが短縮されません。スキーマフィールドのリネームをテストするために、完全なCI/CDパイプラインを待ち、コンテナを再ビルド・再デプロイするのは、イテレーション速度に大きな負担をかけます。

根本的な問題は*孤立*です。開発者のノートパソコンは、クラウド上のライブで相互接続されたグラフから切り離されています。サブグラフトンネルはこの障壁を解消します。


3. ダイナミックサブグラフIngress:トンネリングパターン

ダイナミックサブグラフIngressは、開発者がローカルで単一のサブグラフを動かしながら、トンネリングエージェントがそれをクラウドのステージングスーパグラフに登録し、ライブトラフィックをルーティングするアーキテクチャパターンです。開発者は、他のサービスを動かすことなく、実際の構成済みグラフと完全に連携できます。

クエリ時のデータフローはシンプルです。

クライアント(アプリケーションまたはApollo Sandboxの開発者)は、ステージングスーパグラフのルーターにクエリを送信します。ルーターは操作を解析し、クエリプランを作成します。クラウドホストされたサブグラフ(UsersReviews)によって解決されるフィールドは通常通りフェッチされます。開発中のサブグラフ(Inventory)のフィールドは、安全なトンネルを通じてlocalhost:4000にルーティングされ、ローカルのプロセスがリゾルバを実行し、ローカルまたはリモートのデータベースにアクセスし、ペイロードをトンネル経由で返します。ルーターはこれらの部分結果を集約し、クライアントに統合されたレスポンスを返します。

クライアントから見ると、レスポンスは完全にクラウドホストされたスーパグラフと区別がつきません。開発者から見ると、ローカルのプロセスはライブの構成済みトラフィックに対して完全なデバッグ性(ブレークポイント、変数の検査、スタックトレース)を持ちます。


4. コアアーキテクチャ:3つのコンポーネント

完全なサブグラフトンネルの実装には、3つの連携コンポーネントが必要です。

4.1 ローカルサブグラフ

これは、開発者のマシン上で動作するフェデレーション互換のGraphQLサーバです。@apollo/subgraphを使ったNode.js、Strawberryを使ったPython、gqlgenを使ったGo、DGSを使ったKotlinなど、任意の言語とフレームワークで有効なサブグラフSDLを生成できます。ホットモジュールリプレースメントやライブリロードにより、スキーマ変更は即座に反映され、プロセスの再起動は不要です。

サーバはHTTPポートを公開します。そのポートがトンネルがプロキシするターゲットです。

4.2 セキュアトンネリングエージェント

トンネリングエージェントは、ローカルマシンとパブリックリレーエンドポイント間の永続的かつ認証された接続を確立し、NATや企業ファイアウォールをバイパスします。一般的に使われる本番グレードの選択肢は2つです。

ngrokは、HTTP/2の多重ストリームをngrokのリレーインフラに開き、安定した公開URL(例:https://dev-inventory.ngrok.app)を提供します。受信したHTTPリクエストはトンネル経由でローカルポートにプロキシされます。OAuth 2.0、OpenID Connect、mTLSによる認証は、開発サーバにアクセスする場合は常に設定してください。

Cloudflare Tunnel (cloudflared)も同じ原理で動作します。cloudflaredデーモンはCloudflareのエッジネットワークにアウトバウンド接続を確立し、設定されたホスト名に到達したトラフィックは、その接続を通じてローカルのオリジンにルーティングされます。アウトバウンドのみの接続なので、インバウンドのファイアウォールルールは不要です。

両ツールとも、WebhookスタイルのインスペクションUIをサポートし、トンネルを流れるHTTPリクエストとレスポンスの生データを確認できます。

4.3 ダイナミッククラウドルーター

これは最も複雑なアーキテクチャコンポーネントです。クラウド側のルーターはトンネルURLを認識し、それをターゲットサブグラフの内部ステージングURLの代わりに置き換える必要があります。

静的設定では、スーパグラフSDLはjoin__GraphディレクティブによりルーティングURLをエンコードします。ルーターは起動時にこれらのURLを読み取り、サブ操作を送信します。トンネルを動作させるには、2つの方法があります:構成を更新してトンネルURLを埋め込むか、リクエスト時にURLを上書きするようルーターを拡張します。

これらのアプローチは、それぞれのユースケースに適しています。次のセクションでそのトレードオフを詳しく解説します。


5. ステップバイステップの実装

以下は、ローカルサブグラフをステージングスーパグラフに接続するための標準的な4ステップの手順です。

ステップ1:ローカルサブグラフを起動

npm run dev --port 4000
# → サーバは http://localhost:4000/graphql で稼働

エンドポイントをイントロスペクションして有効なサブグラフSDLを返すことを確認します。

ステップ2:リバーストンネルを開く

ngrok http 4000
# → https://dev-inventory.ngrok.app へフォワーディング

公開URLが有効になりました。https://dev-inventory.ngrok.app/graphqlへのHTTP POSTリクエストはローカルのリゾルバに届きます。

ステップ3:サブグラフのルーティングURLを上書き

Rover CLIを使い、supergraph.yaml設定ファイルでサブグラフのソースを混在させることができます。既存のステージンググラフ参照を使い、他のサブグラフはレジストリから取得しつつ、inventoryエントリのrouting_urlschema.subgraph_urlをトンネルのURLに上書きします。

federation_version: =2.12.0
subgraphs:
  products:
    routing_url: http://products.staging.svc.cluster.local
    schema:
      graphref: my-supergraph@staging
      subgraph: products
  users:
    routing_url: http://users.staging.svc.cluster.local
    schema:
      graphref: my-supergraph@staging
      subgraph: users
  inventory:
    routing_url: https://dev-inventory.ngrok.app/graphql
    schema:
      subgraph_url: https://dev-inventory.ngrok.app/graphql

Roverのサブグラフミラーリング機能(最近のリリースで導入)は、既存のスタジオグラフリファレンスからルーティングURLとスキーマを継承し、フルスーパグラフ設定を維持せずにローカルのスーパグラフを素早く起動できます。開発中のサブグラフだけを明示的に上書きすれば良いです。

rover devを実行すると、複合されたサブグラフ群に対してクエリを行うローカルルーターが起動し、ハイブリッドなローカル/リモート開発環境を提供します。

ステップ4:エンドツーエンドの検証

フロントエンドやApollo Sandboxをローカルルーターのエンドポイント(デフォルトはhttp://localhost:4000)に向けてクエリを実行します。サブグラフトンネルされたサブグラフのサブ操作を受信したら、ルーターはこれらを集約し、統合されたレスポンスを返します。


6. 共有環境:ヘッダーベースのダイナミックIngress

上記のアプローチには、共有クラウドステージングルーターに適用した場合の重大な運用上の欠陥があります。ステージングルーターのサブグラフURLをDeveloper AのノートパソコンのURLに更新すると、Developer BのリクエストやQAの自動テストもDeveloper Aのマシンにルーティングされてしまいます。Developer Aがノートパソコンを閉じると、共有ステージング環境全体が破綻します。

ヘッダーベースのダイナミックIngressは、リクエストごとにルーティングを制御し、グローバルなルーター設定を変更せずに済む仕組みです。

メカニズム

開発者はリクエストにカスタムヘッダーを付与します:

x-dev-routing: inventory=https://dev-inventory.ngrok.app

ルーターはこのヘッダーを検査し、特定のリクエストに対してのみ、inventoryサブグラフのアウトバウンドURLを上書きします。その他のリクエストは従来通り内部ステージングクラスタにルーティングされます。

Rhaiスクリプトによる実装

Apollo Routerは、Rhaiスクリプトを使ったヘッダーやクッキー、ルーターコンテキストのインメモリ操作をサポートします。router_servicesupergraph_serviceexecution_servicesubgraph_serviceといったエントリポイントを通じてリクエスト処理のライフサイクルにフックします。subgraph_serviceフックは、クエリプラン内のサブグラフリクエストごとに呼び出されます。プランが3つのサブグラフに分岐している場合、3回呼び出され、それぞれのターゲットサブグラフの名前を受け取ります。

ヘッダーに基づくルーティング上書きのRhaiスクリプト例:

fn subgraph_service(service, subgraph) {
    let request_callback = |request| {
        let routing_header = request.headers["x-dev-routing"];
        if routing_header != () {
            // "subgraphName=https://tunnel-url"ペアを解析
            let parts = routing_header.split("=");
            if parts.len() == 2 && parts[0].trim() == subgraph {
                request.subgraph.uri = parts[1].trim();
            }
        }
    };
    service.map_request(request_callback);
}

Apolloの公開ベンチマークによると、Rhaiスクリプトのオーバーヘッドはp95で約100µsとされており、このユースケースには適しています。複雑なJWTパースや外部サービス呼び出し、データベースルックアップなど、Rhaiで表現できないロジックには、HTTP経由の外部コプロセッサを使うことも可能です。ただし、コプロセッサのオーバーヘッドは平均350µs程度で、サブグラフのファンアウトに比例して増加します。

コプロセッサはGraphOS Enterpriseプランが必要です。Rhaiスクリプトは、オープンソースのApollo Router Coreバイナリを含むすべてのルーター層で動作します。

分離特性

ヘッダーに基づくルーティングを導入することで、複数の開発者が同時に異なるサブグラフをトンネルし、同じステージングルーターに接続できます。各開発者のリクエストには独自のルーティングヘッダーが含まれ、Rhaiスクリプトは一致するリクエストにのみ上書きを適用します。ステージングルーターの観点からは、グラフは常に構成済みで利用可能です。オフラインになった開発者のリクエストだけに影響します。


7. エコシステム:これらのワークフローをサポートするツール群

Apollo GraphOSとRover CLI

Roverは、フェデレーションスキーマを管理するためのApolloのコマンドラインツールです。rover devはローカルルーターのインスタンスを起動します(最初の一度だけ自動ダウンロード)。このルーターは、GraphOS Studioのグラフリファレンスからサブグラフスキーマを取得し、ローカルで動作するサブグラフと結合します。デフォルトのポートは4000です。

supergraph.yamlフォーマットは、rover supergraph composerover devでサポートされ、3つのスキーマソース(ローカル.graphqlファイル、ライブサブグラフのイントロスペクションURL、既に公開されたGraphOSのグラフリファレンス)を同時に扱えます。これにより、トンネリングワークフローに必要な柔軟性が得られます。

最近のRoverリリースでは、サブグラフミラーリング機能が追加され、既存のStudioグラフリファレンスからルーティングURLとスキーマを継承し、supergraph.yamlを手動で管理する必要がなくなりました。開発中のサブグラフだけを明示的に上書きします。

現在のLTSリリースはv2.10(2025年12月リリース)で、フェデレーションv2.12に対応しています。v1.xは2026年3月31日にサポート終了です。既にv2に移行済みのチームは特に変更は不要です。

GraphQL Hive

The Guildが運営するGraphQL Hiveは、完全オープンソースのMITライセンスの代替ツールです。スキーマレジストリ、構成検証、利用状況分析、独自のゲートウェイ(Hive Gateway in JavaScript、Hive Router in Rust)を提供します。レジストリは、構成されたスーパグラフを高可用性のCDNに公開し、ゲートウェイは定期的に更新をポーリングします。

Hiveは、ブランチされたスキーマ環境(developmentstagingproductionターゲットがデフォルト作成)と、ターゲット間のスキーマ昇格をサポートします。サブグラフのrouting_urlを開発ターゲットに公開し、ステージングや本番ターゲットはそのままにできます。

2025年3月12日、Hiveはレジストリアクセストークンをターゲットごとから組織レベルのアクセストークンに移行しました。これにより、特定のプロジェクトやターゲットにスコープを限定できます。古い--registry.accessTokenフラグを使ったツールは、--target引数も必要です。

Hive GatewayとHive Router

Hive Gateway(Node.js)とHive Router(Rust)は、Hive CDNから構成済みスーパグラフのアーティファクトをポーリングします。フェデレーションの構成をサポートしているため、routing_urlを公開し、開発ターゲットのサブグラフに設定すれば、ゲートウェイはそれに従ってルーティングします。


8. セキュリティと運用上の考慮点

トンネル認証

ローカル開発サーバをインターネットに公開するのはリスクがあります。悪意のある者がURLを発見すると、任意のGraphQL操作をPOSTでき、開発者レベルの資格情報や環境変数、データベース、秘密情報にアクセスされる可能性があります。

トンネル層で認証を強制し、アプリケーション層だけでなく、ngrokやcloudflaredのOAuth 2.0やmTLSを設定してください。クラウドルーターには、共有シークレットやクライアント証明書をリクエストに含める設定を行い、ローカルトンネルエージェントがそれを検証します。

本番やステージングのデータに書き込み権限のあるサブグラフのURLをmTLSや同等の認証なしで公開しないでください。

イントロスペクションとスキーマ露出

ローカルサブグラフをトンネル経由でステージングスーパグラフに接続すると、スーパグラフのスキーマと操作ポリシーがルーターのエッジに適用されます。ただし、ローカルサブグラフのイントロスペクションが制限なく有効になっている場合、URLを知っている者はスキーマを検査できてしまいます。

Apollo Router v1.0以降は、非開発モードではイントロスペクションはデフォルトで無効です。セキュリティ要件に応じて設定を確認してください。

nullabilityと部分的な失敗

ローカル開発環境は不安定です。ブレークポイントで停止したり、リクエスト中にサーバを再起動したり、コンパイルエラーでプロセスが停止したりすると、トンネルはタイムアウトやエラーを返します。

フェデレーテッドスキーマはnullabilityを考慮して設計すると、これらの失敗の影響を限定できます。サブグラフが応答しない場合、ルーターはエラーを返すのではなく、そのエンティティのブランチにnullを返すことが可能です。Apolloのnullabilityに関するドキュメントでは、内部SLAに応じてnull許容性を評価することを推奨しています。すべてのサービス間結合でnullableにするのが安全なアプローチです。

@semanticNonNullディレクティブは、nullがエラー配列のエントリの存在にのみ現れることを示し、ビジネス値としてのnullを避けるための表現力豊かな方法です。これにより、クライアントは型付けされたコードで非nullプロパティを生成しつつ、トンネルダウンしたサブグラフがオフラインになるリスクを管理できます。

@deferも役立ちます。遅延を伴うローカルサブグラフのトンネルでは、@deferを使って、遅延しない部分を即座に受け取り、ローカル結果を非同期で待つことができます。

分散トレーシング

複雑なクエリプランの実行をデバッグするには、エンドツーエンドのトレース可視性が必要です。クラウドホストとローカルトンネルサブグラフの両方にまたがるトレースは、すべてをカバーすべきです。

Apollo Routerは、W3C Trace Context仕様に従い、traceparenttracestateヘッダーを自動的にサブグラフリクエストに含めます。OpenTelemetryを使ってローカルサブグラフを計測している場合、@opentelemetry/instrumentation-graphqlとOTLPエクスポーターを設定すれば、分散トレース内で親子関係のスパンとして表示されます。

router.yamltelemetry設定で、trace_context: trueを有効にすると、W3Cヘッダーが伝播されます。

telemetry:
  exporters:
    tracing:
      propagation:
        trace_context: true
      otlp:
        enabled: true
        endpoint: "http://localhost:4317"

このトレースのウォーターフォールは、クエリプランニング、並列サブグラフフェッチ、ローカルリゾルバのスパンを追跡でき、フェデレーションN+1問題の分析に最も有効なデバッグツールです。


9. 運用成熟度:チームで標準化すべきポイント

個々の開発者の実験から、チーム全体でのトンネリング運用へ移行する際に、摩擦を減らし事故を防ぐための運用規範をいくつか紹介します。

トンネルライフサイクルの自動化。 ngrokの再起動ごとにURLは変わるため、予約済みドメインを設定して安定させることを推奨します。トンネルURLの登録は、開発開始スクリプトに組み込みましょう。

コプロセッサとRhaiの使い分け。 Rhaiスクリプトはルーター内で直接動作し、追加インフラ不要です。ヘッダー解析は多くのチームにとってRhaiで十分です。外部状態に依存する場合は、コプロセッサを使います。例えば、共有ストアに保持された開発者IDとトンネルURLのマッピングです。

ステージングルーターの孤立化。 共有ステージングルーターには、ヘッダーによるルーティングを適用し、グローバルなサブグラフURLの置換は避けましょう。短期間の機能ブランチや、開発者が全体のステージング環境を所有している場合にのみ適用します。

CIでのスキーマ構成検証。 ローカルトンネルを使っていても、マージ前に構成検証を行うべきです。rover subgraph checkやHive CLIのhive schema:checkで、レジストリの現在の構成と比較し、破壊的変更を検出します。

トンネル範囲のセキュリティレビュー。 どのサブグラフをトンネル化できるかを定義し、ドキュメント化します。書き込み権限のあるサブグラフは、認証を強化し、公開前にレビューを行う必要があります。


10. まとめ

GraphQLフェデレーションの本来の目的は、チームの自主性—所有権、デプロイ、イテレーションの独立性—を実現することでした。開発者のハードウェアの制約は、その約束を損なうものでした。

サブグラフのトンネリングはこれを復元します。特定のサブグラフのトラフィックを安全なトンネル経由で開発者のノートパソコンにルーティングし、他のサブグラフはクラウドで動かし続けることで、エンジニアはライブグラフに対して高忠実度でデバッグ可能なアクセスを得られます。

ツールは大きく成熟しています。rover devのサブグラフミラーリング、Apollo RouterのRhaiスクリプト、Hiveのブランチスキーマレジストリは、実運用に耐えるワークフローの構成要素です。現在の安定基盤は、フェデレーションv2.12対応のApollo Router v2.x(2025年12月リリース)です。v1.xは2026年3月にサポート終了です。

ヘッダーベースのリクエストごとのルーティングは、チームスケールのパターンです。複数の開発者が異なるサブグラフを同時にトンネルし、完全に孤立した状態で同じルーターを共有します。これが標準化すべきワークフローです。


変更履歴

変更点 理由
目次からターゲットキーワードとフックラインを削除 メタデータのため、編集内容ではない
セクション3の図解説明を書き換え 元のルーターの内部ステージングDNSとリレーの混同を解消
apollo Rover CLI rover devの説明を正確な動作に更新 rover devはローカルルーターを起動し、共有クラウドステージングには影響しない。ミラーリングの説明を追加
supergraph.yaml例をfederation_version: =2.12.0に更新 2025年12月のフェデレーションLTSバージョンに合わせる
Apollo Router v2.10 / Federation v2.12のリリース(2025年12月)とv1.xのサポート終了(2026年3月31日)を追記 公式情報に基づく
Rhaiスクリプト例を公式APIリファレンスに合わせて書き直し 公式ドキュメントのsubgraph_serviceフックとヘッダーアクセスパターンに準拠
コプロセッサのパフォーマンス例(約100µs / 約350µs)を追加 Apolloの公開ベンチマークから
コプロセッサはGraphOS Enterpriseプランが必要と明記 公式Routerドキュメントより
WunderGraphの記述を削除 会社の新方針により削除
GraphQL Hiveの内容をリライトし、Hive Gateway v2とHive Routerの詳細、2025年3月のトークン移行、CDN配信を追加 公式Hiveドキュメントに基づく
@semanticNonNullディレクティブの説明を追加 失敗時のハンドリングに関する最新情報、2024年8月のApollo Kotlinの情報に基づく
OpenTelemetryのトレース設定例を追加 公式Router telemetryドキュメントに準拠
セクション9(運用成熟度)を追加 チーム運用の観点からの標準化ポイントを解説

Continue from this article into the most relevant product guides and workflows.

Related Topics

#Apollo Federation local development, GraphQL subgraph tunnel, dynamic supergraph ingress, federated GraphQL proxy, remote schema stitching, Apollo Router integration, schema composition edge, localized subgraph routing, GraphOS gateway tunnel, distributed graph architecture, corporate GraphQL ingress, testing subgraphs locally, schema mesh network, managed federation gateway, Apollo Federation 2, query planning proxy, subgraph synchronization, reverse proxy for GraphQL, enterprise graph routing, federated microservices testing, hot-reloading schemas cloud, client-side graph execution, intercepting GraphQL queries, Rover CLI tunnel orchestration, continuous integration GraphQL, zero-trust schema stitching, decoupling microservices dev, cloud-to-localhost graph gateway, GraphQL federation 2026, real-time graph telemetry

Keep building with InstaTunnel

Read the docs for implementation details or compare plans before you ship.

Share this article

More InstaTunnel Insights

Discover more tutorials, tips, and updates to help you build better with localhost tunneling.

Browse All Articles