はじめに:「異なる言語間のRPCって、普通は大変では?」

マイクロサービスを運用した経験のある方なら共感いただけると思いますが、異なる言語で書かれたサービス同士を連携させるには、従来は次のような手間が必要でした。

  • Protobuf や Thrift などの IDL を別途定義し
  • スキーマ変更のたびに コード生成(Codegen) を回し直し
  • 言語ごとに シリアライズ/デシリアライズ層 を個別に管理

今回Cloudflareが公開した クロスランゲージRPC は、この常識を根本から覆します。Python WorkerからTypeScript Workerのメソッドを await rpc.add(42, 144) の一行でそのまま呼び出せます。スキーマも、依存追加も、ビルドステップも不要です。

本記事では、この機能が なぜ実現できるのか実務でどう活用できるのか、そして どこに注意すべきか を整理します。👉 根拠資料

Server architecture diagram showing cross-language RPC communication between Python and JavaScript Workers Developer Related Image

核心:スキーマなしで言語をまたぐRPC

TypeScript Workerでメソッドを定義

import { WorkerEntrypoint } from "cloudflare:workers";

export class RpcService extends WorkerEntrypoint {
  async add(a: number, b: number): Promise<number> {
    // 2つの数値を足して返します。
    return a + b;
  }
}

Python Workerからそのまま呼び出す

from workers import Response, WorkerEntrypoint

class Default(WorkerEntrypoint):
    async def fetch(self, request):
        # TypeScript WorkerのRPCスタブを取得します。
        rpc = self.env.RPC
        # TypeScriptのRPCメソッドをそのまま呼び出します。
        result = await rpc.add(42, 144)
        return Response.json({"result": result})

Service bindingを追加するだけ

"services": [
  {
    "binding": "RPC",
    "service": "ts-rpc-server",
    "entrypoint": "RpcService"
  }
]

はい、これだけです。Protobufも、スキーマのコード生成も、追加SDKのインストールも不要 です。

内部では何が起きているのか

鍵となるのは PyodideのFFI(Foreign Function Interface) です。Python WorkerはCPythonをWebAssemblyにコンパイルしたPyodide上で動作しており、このFFIがJavaScriptとPython間の型を自動変換します。

Python型JavaScript型
int, floatNumber
boolBoolean
dictObject
listArray
datetimeDate

直接変換できないカスタムクラスや関数は Proxyオブジェクト でラップされ、属性アクセスやメソッド呼び出しがそのまま転送されます。たとえばPython関数をJavaScriptのコールバックとして渡すようなパターンも自然に動作します。

キーワード引数もスマートにマッピングされます。JavaScript側で get(key, options?) として定義されたメソッドを、Pythonから JSRPC.get("myKey", type="text") のように呼び出すと、内部的に { type: "text" } オブジェクトへ変換されます。Python開発者はPythonらしく、JS開発者はJSらしく書けばよい設計です。

Python and JavaScript code snippets side by side demonstrating Cloudflare Workers RPC method calls Development Concept Image

注意点:Web APIオブジェクトには専用SDKが必要です

Pyodide FFIは基本型を自動変換してくれますが、RequestResponseBlobFile といったWeb APIオブジェクトは自動変換の対象外 です。これらはCloudflare Workersで頻繁に使われる型ですが、Pythonにはネイティブの対応型が存在しません。

デフォルトの挙動では、これらのオブジェクトは JavaScript Proxyとしてラップされたまま 渡されます。そのため、Pythonコードの中にJS実装の詳細が漏れ出し、開発者のメンタルモデルが煩雑になります。

この問題を解決するために、Cloudflareは workers-runtime-sdk というPythonパッケージを提供しています。uv run pywrangler deploy でデプロイすると自動的に含まれ、from workers import Response のように workers 名前空間からインポートする時点で既に利用していることになります。

このSDKが言語境界を越えるオブジェクトをインターセプトし、両言語で自然に扱えるネイティブな形へ変換します。

実践例:PythonパッケージをJavaScriptから使う

JavaScriptアプリでPygments(Python製のシンタックスハイライター)を使いたい場合は次のとおりです。

// JavaScript Worker: Python Workerのメソッドを呼び出します。
export default {
  async fetch(request, env) {
    const rpc = env.PYTHON_RPC;
    const result = await rpc.highlight_code('print(42)', 'python');
    return Response.json(result);
  }
}
# Python Worker: Pygmentsを使ってハイライトを実行します。
from workers import WorkerEntrypoint
from pygments.formatters import HtmlFormatter
from pygments import highlight
from pygments.lexers import get_lexer_by_name

class Default(WorkerEntrypoint):
    async def highlight_code(self, code: str, language: str) -> dict:
        # 指定された言語のレクサーを取得します。
        lexer = get_lexer_by_name(language, stripall=True)
        # フォーマッターを作成し、ハイライトを実行します。
        formatter = HtmlFormatter(linenos=True, cssclass="highlight", style="monokai")
        highlighted_html = highlight(code, lexer, formatter)
        # スタイル用のCSSを取得します。
        css = formatter.get_style_defs(".highlight")
        return {"html": highlighted_html, "css": css}

JS Worker側の wrangler.jsonc にはService bindingを追加するだけです。

"services": [
  { "binding": "PYTHON_RPC", "service": "py-rpc-server" }
]

この技術の限界と注意事項

  • RPCはほとんどの場合ネットワークを越えません。 同一スレッド上で動作するためパフォーマンスオーバーヘッドはほぼゼロですが、その分 Worker間の分離レベルが低い ことを意味します。障害分離(Fault Isolation)が必要な場合は別途設計が必要です。
  • Python Workerのコールドスタート はPyodide(WASM)のロードがあるため、純粋なJS Workerより遅くなります。レイテンシに敏感な経路には不向きな場合があります。
  • Pyodide FFIが捉えないカスタム型 は依然としてProxyとして渡されるため、予期しない箇所でJSオブジェクトのように振る舞う可能性があります。型ヒントを明確に記述する習慣が有効です。
  • 両方のWorkerを別々のターミナルでdevサーバーとして起動する必要 があり、ローカル開発体験はまだ洗練されていません。

次のステップ学習の方向性

  • 公式ドキュメントの Python Workers RPC ガイド を一通り確認し
  • python-workers-examples リポジトリで実際のサンプルを動かしてみてください。
  • Pyodide FFIの型マッピング規則を理解しておくと、デバッグ速度が大きく向上します。

Cloud infrastructure visualization of Cloudflare Workers runtime bridging Python and JavaScript execution

まとめ:「言語の境界は、今やライブラリ呼び出しのように」

Cloudflare WorkersのクロスランゲージRPCは、スキーマ・コード生成・シリアライズ層なしで PythonとJavaScriptを一つのアプリケーションのように組み合わせる機能です。整理すると次のとおりです。

  1. Service binding + メソッド呼び出し だけで言語をまたぐRPCが成立
  2. Pyodide FFI が基本型を自動変換、カスタム型はProxyで転送
  3. workers-runtime-sdk がWeb APIオブジェクトまで自然に扱えるようにする
  4. 一方で コールドスタート、分離レベル、ローカルDX にはまだトレードオフが存在

併せて読みたい記事

本コンテンツは、信頼性の高い情報源をもとにAIツールを活用して作成され、編集者によるレビューを経て公開されています。専門家によるアドバイスの代替となるものではありません。