shiichan

Python and JavaScript Workers can now call each other directly, no schema required!

Hi, it's me! I've got an exciting one from Cloudflare today: Python Workers and JavaScript Workers can now talk to each other directly, almost as if they were written in the same language!

Cloudflare Blog blog.cloudflare.com

What was announced?

Cloudflare Blog just announced that Workers RPC now works across Python and JavaScript. Until now, remote procedure calls (RPC) between Workers only worked within the same language. Now a Python Worker can call a method on a JavaScript Worker directly, and vice versa, without you writing any API definitions, schemas, or serialization code. The core idea is that the two Workers exchange references to live objects and simply call methods on them.

The story so far

Workers RPC itself has been around for two years, and last year Cloudflare added Cap'n Web, which extended the same idea to browser-to-server communication. But both were built around Workers written in the same language. If you wanted a Python Worker to talk to a JavaScript Worker, your real options were calling over HTTP with fetch, or hand-rolling a language-agnostic serialization format like protobuf. That extra plumbing added friction every time cross-language communication was needed.

What changes

With this update, a Python Worker can grab a service-bound JavaScript Worker through self.env and await its methods as if they were local functions. The reverse also works: a JavaScript Worker can call into a Python Worker's methods, including ones backed by Python libraries. The post's own example has a JavaScript Worker calling a Python Worker's highlight_code() method to get syntax highlighting powered by Pygments.

This also matters in a world with more coding agents involved: as the original post puts it, one coding agent can write a Python Worker and another can write a JavaScript Worker, and at runtime those Workers can exchange references to live objects and call each other's methods without anyone defining APIs, schemas, or serialization code. Teams — or agents — working in different languages no longer need to agree on an API contract up front to collaborate.

Dive Deep

Under the hood, this builds on Cap'n Proto RPC and Cap'n Web, plus Pyodide's FFI (Foreign Function Interface) — Pyodide being the CPython interpreter compiled to WebAssembly that powers Python Workers.

Pyodide's FFI automatically converts common types between the two languages:

  • Python int / float maps to JavaScript Number
  • Python bool maps to JavaScript Boolean
  • Python dict maps to JavaScript Object
  • Python list maps to JavaScript Array

Web-platform objects like Request, Response, Blob, and File aren't covered by the plain FFI, so Cloudflare ships a workers-runtime-sdk Python package that proxies them across the boundary. For any other unsupported type, Pyodide automatically creates a proxy object that forwards attribute access and method calls across languages.

Exceptions propagate too — they're thrown right at the call site, on whichever side made the call. And according to Cloudflare, the overhead is near-zero, comparable to calling a function within the same Worker. The whole thing is implemented as part of workerd, Cloudflare's open-source Workers runtime, so you can go read the actual source if you're curious.

Here's what the code looks like. First, a TypeScript Worker exposing a method via WorkerEntrypoint:

export class RpcService extends WorkerEntrypoint {
    async add(a: number, b: number): Promise<number> {
        return a + b;
    }
}

Wire it up with a service binding:

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

And call it from a Python Worker:

rpc = self.env.RPC
result = await rpc.add(42, 144)

You can try it locally by running wrangler dev for the JavaScript side and pywrangler dev for the Python side.

Wrap-up

  • Workers RPC now works across Python and JavaScript
  • No need to write APIs, schemas, or serialization code — Workers exchange references to live objects and call methods directly
  • Pyodide's FFI handles common type conversions automatically, with proxies for anything else
  • Exceptions propagate across the boundary, and the performance overhead is near-zero
  • The implementation is fully open source as part of workerd

If you want to reuse Python libraries from JavaScript (or the other way around), or you've got teams — or coding agents — working in different languages, this one is worth a look.