releases.sh

Cross-language RPC between Python and JavaScript Workers

1 featureThis release1 featureNew capabilitiesAI-tallied from the release notes
From the original release noteView original ↗

You can now call methods between Python and JavaScript Workers using Workers RPC. This works through Service bindings without extra dependencies, schema definitions, or serialization code.

Cross-language RPC calls behave like ordinary function calls. Exceptions propagate to the call site. You can pass structured cloneable types ↗ as parameters or return values, and Pyodide Foreign Function Interface (FFI) automatically converts types between languages.

Call a TypeScript Worker from Python

Define a method in a TypeScript Worker:

index.jsjs

<span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { WorkerEntrypoint } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "cloudflare:workers"</span><span class="nb-shiki-140thh">;</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1itgoe">export</span><span class="nb-shiki-1itgoe"> class</span><span class="nb-shiki-1t8gfj"> RpcService</span><span class="nb-shiki-1itgoe"> extends</span><span class="nb-shiki-1t8gfj"> WorkerEntrypoint</span><span class="nb-shiki-140thh"> {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">	async</span><span class="nb-shiki-1t8gfj"> add</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1jdh33">a</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">b</span><span class="nb-shiki-140thh">) {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		return</span><span class="nb-shiki-140thh"> a </span><span class="nb-shiki-1itgoe">+</span><span class="nb-shiki-140thh"> b;</span></span>
<span class="line"><span class="nb-shiki-140thh">	}</span></span>
<span class="line"><span class="nb-shiki-140thh">}</span></span>

index.tsts

<span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { WorkerEntrypoint } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "cloudflare:workers"</span><span class="nb-shiki-140thh">;</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1itgoe">export</span><span class="nb-shiki-1itgoe"> class</span><span class="nb-shiki-1t8gfj"> RpcService</span><span class="nb-shiki-1itgoe"> extends</span><span class="nb-shiki-1t8gfj"> WorkerEntrypoint</span><span class="nb-shiki-140thh"> {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">	async</span><span class="nb-shiki-1t8gfj"> add</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1jdh33">a</span><span class="nb-shiki-1itgoe">:</span><span class="nb-shiki-dzsirb"> number</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">b</span><span class="nb-shiki-1itgoe">:</span><span class="nb-shiki-dzsirb"> number</span><span class="nb-shiki-140thh">)</span><span class="nb-shiki-1itgoe">:</span><span class="nb-shiki-1t8gfj"> Promise</span><span class="nb-shiki-140thh"><</span><span class="nb-shiki-dzsirb">number</span><span class="nb-shiki-140thh">> {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		return</span><span class="nb-shiki-140thh"> a </span><span class="nb-shiki-1itgoe">+</span><span class="nb-shiki-140thh"> b;</span></span>
<span class="line"><span class="nb-shiki-140thh">	}</span></span>
<span class="line"><span class="nb-shiki-140thh">}</span></span>

Call it from a Python Worker through a Service binding:

<span class="line"><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-140thh"> workers </span><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> Response, WorkerEntrypoint</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1itgoe">class</span><span class="nb-shiki-1t8gfj"> Default</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1t8gfj">WorkerEntrypoint</span><span class="nb-shiki-140thh">):</span></span>
<span class="line"><span class="nb-shiki-1itgoe">	async</span><span class="nb-shiki-1itgoe"> def</span><span class="nb-shiki-1t8gfj"> fetch</span><span class="nb-shiki-140thh">(self, request):</span></span>
<span class="line"><span class="nb-shiki-140thh">		rpc </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-dzsirb"> self</span><span class="nb-shiki-140thh">.env.</span><span class="nb-shiki-dzsirb">RPC</span></span>
<span class="line"><span class="nb-shiki-140thh">		result </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> rpc.add(</span><span class="nb-shiki-dzsirb">42</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-dzsirb">144</span><span class="nb-shiki-140thh">)</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		return</span><span class="nb-shiki-140thh"> Response.json({</span><span class="nb-shiki-mdbnqw">"result"</span><span class="nb-shiki-140thh">: result})</span></span>

Configure the Service binding in the Python Worker's Wrangler configuration:

<span class="line"><span class="nb-shiki-140thh">{</span></span>
<span class="line"><span class="nb-shiki-dzsirb">	"services"</span><span class="nb-shiki-140thh">: [</span></span>
<span class="line"><span class="nb-shiki-140thh">		{</span></span>
<span class="line"><span class="nb-shiki-dzsirb">			"binding"</span><span class="nb-shiki-140thh">: </span><span class="nb-shiki-mdbnqw">"RPC"</span><span class="nb-shiki-140thh">,</span></span>
<span class="line"><span class="nb-shiki-dzsirb">			"service"</span><span class="nb-shiki-140thh">: </span><span class="nb-shiki-mdbnqw">"ts-rpc-server"</span><span class="nb-shiki-140thh">,</span></span>
<span class="line"><span class="nb-shiki-dzsirb">			"entrypoint"</span><span class="nb-shiki-140thh">: </span><span class="nb-shiki-mdbnqw">"RpcService"</span></span>
<span class="line"><span class="nb-shiki-140thh">		}</span></span>
<span class="line"><span class="nb-shiki-140thh">	]</span></span>
<span class="line"><span class="nb-shiki-140thh">}</span></span>
<span class="line"><span class="nb-shiki-140thh">[[</span><span class="nb-shiki-1t8gfj">services</span><span class="nb-shiki-140thh">]]</span></span>
<span class="line"><span class="nb-shiki-140thh">binding = </span><span class="nb-shiki-mdbnqw">"RPC"</span></span>
<span class="line"><span class="nb-shiki-140thh">service = </span><span class="nb-shiki-mdbnqw">"ts-rpc-server"</span></span>
<span class="line"><span class="nb-shiki-140thh">entrypoint = </span><span class="nb-shiki-mdbnqw">"RpcService"</span></span>
Call a Python Worker from JavaScript

Define a method in a Python Worker:

<span class="line"><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-140thh"> workers </span><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> WorkerEntrypoint</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1itgoe">class</span><span class="nb-shiki-1t8gfj"> Default</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1t8gfj">WorkerEntrypoint</span><span class="nb-shiki-140thh">):</span></span>
<span class="line"><span class="nb-shiki-1itgoe">	async</span><span class="nb-shiki-1itgoe"> def</span><span class="nb-shiki-1t8gfj"> highlight_code</span><span class="nb-shiki-140thh">(self, code: </span><span class="nb-shiki-dzsirb">str</span><span class="nb-shiki-140thh">, language: </span><span class="nb-shiki-dzsirb">str</span><span class="nb-shiki-140thh">) -> </span><span class="nb-shiki-dzsirb">dict</span><span class="nb-shiki-140thh">:</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		from</span><span class="nb-shiki-140thh"> pygments.formatters </span><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> HtmlFormatter</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		from</span><span class="nb-shiki-140thh"> pygments </span><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> highlight</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		from</span><span class="nb-shiki-140thh"> pygments.lexers </span><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> get_lexer_by_name</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-140thh">		lexer </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-140thh"> get_lexer_by_name(language, </span><span class="nb-shiki-1jdh33">stripall</span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-dzsirb">True</span><span class="nb-shiki-140thh">)</span></span>
<span class="line"><span class="nb-shiki-140thh">		formatter </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-140thh"> HtmlFormatter(</span><span class="nb-shiki-1jdh33">linenos</span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-dzsirb">True</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">cssclass</span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-mdbnqw">"highlight"</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">style</span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-mdbnqw">"monokai"</span><span class="nb-shiki-140thh">)</span></span>
<span class="line"><span class="nb-shiki-140thh">		highlighted_html </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-140thh"> highlight(code, lexer, formatter)</span></span>
<span class="line"><span class="nb-shiki-140thh">		css </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-140thh"> formatter.get_style_defs(</span><span class="nb-shiki-mdbnqw">".highlight"</span><span class="nb-shiki-140thh">)</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1itgoe">		return</span><span class="nb-shiki-140thh"> {</span></span>
<span class="line"><span class="nb-shiki-mdbnqw">			"html"</span><span class="nb-shiki-140thh">: highlighted_html,</span></span>
<span class="line"><span class="nb-shiki-mdbnqw">			"css"</span><span class="nb-shiki-140thh">: css</span></span>
<span class="line"><span class="nb-shiki-140thh">		}</span></span>

Call it from a JavaScript Worker through a Service binding:

index.jsjs

<span class="line"><span class="nb-shiki-1itgoe">export</span><span class="nb-shiki-1itgoe"> default</span><span class="nb-shiki-140thh"> {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">	async</span><span class="nb-shiki-1t8gfj"> fetch</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1jdh33">request</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">env</span><span class="nb-shiki-140thh">) {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		const</span><span class="nb-shiki-dzsirb"> rpc</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-140thh"> env.</span><span class="nb-shiki-dzsirb">PYTHON_RPC</span><span class="nb-shiki-140thh">;</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		const</span><span class="nb-shiki-dzsirb"> result</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> rpc.</span><span class="nb-shiki-1t8gfj">highlight_code</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"print(42)"</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-mdbnqw">"python"</span><span class="nb-shiki-140thh">);</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		return</span><span class="nb-shiki-140thh"> Response.</span><span class="nb-shiki-1t8gfj">json</span><span class="nb-shiki-140thh">(result);</span></span>
<span class="line"><span class="nb-shiki-140thh">	},</span></span>
<span class="line"><span class="nb-shiki-140thh">};</span></span>

index.tsts

<span class="line"><span class="nb-shiki-1itgoe">export</span><span class="nb-shiki-1itgoe"> default</span><span class="nb-shiki-140thh"> {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">	async</span><span class="nb-shiki-1t8gfj"> fetch</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1jdh33">request</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">env</span><span class="nb-shiki-140thh">) {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		const</span><span class="nb-shiki-dzsirb"> rpc</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-140thh"> env.</span><span class="nb-shiki-dzsirb">PYTHON_RPC</span><span class="nb-shiki-140thh">;</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		const</span><span class="nb-shiki-dzsirb"> result</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> rpc.</span><span class="nb-shiki-1t8gfj">highlight_code</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"print(42)"</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-mdbnqw">"python"</span><span class="nb-shiki-140thh">);</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		return</span><span class="nb-shiki-140thh"> Response.</span><span class="nb-shiki-1t8gfj">json</span><span class="nb-shiki-140thh">(result);</span></span>
<span class="line"><span class="nb-shiki-140thh">	},</span></span>
<span class="line"><span class="nb-shiki-140thh">};</span></span>

Configure the Service binding in the JavaScript Worker's Wrangler configuration:

<span class="line"><span class="nb-shiki-140thh">{</span></span>
<span class="line"><span class="nb-shiki-dzsirb">	"services"</span><span class="nb-shiki-140thh">: [</span></span>
<span class="line"><span class="nb-shiki-140thh">		{</span></span>
<span class="line"><span class="nb-shiki-dzsirb">			"binding"</span><span class="nb-shiki-140thh">: </span><span class="nb-shiki-mdbnqw">"PYTHON_RPC"</span><span class="nb-shiki-140thh">,</span></span>
<span class="line"><span class="nb-shiki-dzsirb">			"service"</span><span class="nb-shiki-140thh">: </span><span class="nb-shiki-mdbnqw">"py-rpc-server"</span></span>
<span class="line"><span class="nb-shiki-140thh">		}</span></span>
<span class="line"><span class="nb-shiki-140thh">	]</span></span>
<span class="line"><span class="nb-shiki-140thh">}</span></span>
<span class="line"><span class="nb-shiki-140thh">[[</span><span class="nb-shiki-1t8gfj">services</span><span class="nb-shiki-140thh">]]</span></span>
<span class="line"><span class="nb-shiki-140thh">binding = </span><span class="nb-shiki-mdbnqw">"PYTHON_RPC"</span></span>
<span class="line"><span class="nb-shiki-140thh">service = </span><span class="nb-shiki-mdbnqw">"py-rpc-server"</span></span>

For more details on the announcement, read the blog post ↗.

For more information, refer to the Workers RPC documentation and the Python Workers overview.

Fetched August 3, 2026

Cross-language RPC between Python and JavaScript Workers —… — releases.sh