You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
To use RPC, [define a compatibility date](/workers/configuration/compatibility-dates) of `2024-04-03` or higher, or include `rpc` in your [compatibility flags](/workers/configuration/compatibility-flags/#nodejs-compatibility-flag).
14
19
:::
15
20
16
21
Workers provide a built-in, JavaScript-native [RPC (Remote Procedure Call)](https://en.wikipedia.org/wiki/Remote_procedure_call) system, allowing you to:
17
22
18
-
* Define public methods on your Worker that can be called by other Workers on the same Cloudflare account, via [Service Bindings](/workers/runtime-apis/bindings/service-bindings/rpc)
19
-
* Define public methods on [Durable Objects](/durable-objects) that can be called by other workers on the same Cloudflare account that declare a binding to it.
23
+
- Define public methods on your Worker that can be called by other Workers on the same Cloudflare account, via [Service Bindings](/workers/runtime-apis/bindings/service-bindings/rpc)
24
+
- Define public methods on [Durable Objects](/durable-objects) that can be called by other workers on the same Cloudflare account that declare a binding to it.
20
25
21
26
The RPC system is designed to feel as similar as possible to calling a JavaScript function in the same Worker. In most cases, you should be able to write code in the same way you would if everything was in a single Worker.
22
27
@@ -42,11 +47,11 @@ As an exception to Structured Clone, application-defined classes (or objects wit
42
47
43
48
The RPC system also supports a number of types that are not Structured Cloneable, including:
44
49
45
-
* Functions, which are replaced by stubs that call back to the sender.
46
-
* Application-defined classes that extend `RpcTarget`, which are similarly replaced by stubs.
47
-
*[ReadableStream](/workers/runtime-apis/streams/readablestream/) and [WriteableStream](/workers/runtime-apis/streams/writablestream/), with automatic streaming flow control.
48
-
*[Request](/workers/runtime-apis/request/) and [Response](/workers/runtime-apis/response/), for conveniently representing HTTP messages.
49
-
* RPC stubs themselves, even if the stub was received from a third Worker.
50
+
- Functions, which are replaced by stubs that call back to the sender.
51
+
- Application-defined classes that extend `RpcTarget`, which are similarly replaced by stubs.
52
+
-[ReadableStream](/workers/runtime-apis/streams/readablestream/) and [WriteableStream](/workers/runtime-apis/streams/writablestream/), with automatic streaming flow control.
53
+
-[Request](/workers/runtime-apis/request/) and [Response](/workers/runtime-apis/response/), for conveniently representing HTTP messages.
54
+
- RPC stubs themselves, even if the stub was received from a third Worker.
But consider the case where the Worker service that you are calling may be far away across the network, as in the case of [Smart Placement](/workers/runtime-apis/bindings/service-bindings/#smart-placement) or [Durable Objects](/durable-objects). The code above makes two round trips, once when calling `getCounter()`, and again when calling `.increment()`. We'd like to avoid this.
171
186
172
187
With most RPC systems, the only way to avoid the problem would be to combine the two calls into a single "batch" call, perhaps called `getCounterAndIncrement()`. However, this makes the interface worse. You wouldn't design a local interface this way.
173
188
174
189
Workers RPC allows a different approach: You can simply omit the first `await`:
In this code, `getCounter()` returns a promise for a counter. Normally, the only thing you would do with a promise is `await` it. However, Workers RPC promises are special: they also allow you to initiate speculative calls on the future result of the promise. These calls are sent to the server immediately, without waiting for the initial call to complete. Thus, multiple chained calls can be completed in a single round trip.
183
202
184
203
How does this work? The promise returned by an RPC is not a real JavaScript `Promise`. Instead, it is a custom ["Thenable"](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#thenables). It has a `.then()` method like `Promise`, which allows it to be used in all the places where you'd use a normal `Promise`. For instance, you can `await` it. But, in addition to that, an RPC promise also acts like a stub. Calling any method name on the promise forms a speculative call on the promise's eventual result. This is known as "promise pipelining".
185
204
186
205
This works when calling properties of objects returned by RPC methods as well. For example:
If the initial RPC ends up throwing an exception, then any pipelined calls will also fail with the same exception
213
240
214
241
## ReadableStream, WriteableStream, Request and Response
215
242
216
-
You can send and receive [`ReadableStream`](/workers/runtime-apis/streams/readablestream/), [`WriteableStream`](/workers/runtime-apis/streams/writablestream/), [`Request`](/workers/runtime-apis/request/), and [`Response`](/workers/runtime-apis/response/) using RPC methods. When doing so, bytes in the body are automatically streamed with appropriate flow control.
243
+
You can send and receive [`ReadableStream`](/workers/runtime-apis/streams/readablestream/), [`WriteableStream`](/workers/runtime-apis/streams/writablestream/), [`Request`](/workers/runtime-apis/request/), and [`Response`](/workers/runtime-apis/response/) using RPC methods. When doing so, bytes in the body are automatically streamed with appropriate flow control. This allows you to send messages over RPC which are larger than [the typical 32 MiB limit](#limitations).
217
244
218
245
Only [byte-oriented streams](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_byte_streams) (streams with an underlying byte source of `type: "bytes"`) are supported.
219
246
@@ -223,11 +250,15 @@ In all cases, ownership of the stream is transferred to the recipient. The sende
223
250
224
251
A stub received over RPC from one Worker can be forwarded over RPC to another Worker.
225
252
226
-
```js
253
+
<TypeScriptExample>
254
+
255
+
```ts
227
256
usingcounter=env.COUNTER_SERVICE.getCounter();
228
257
awaitenv.ANOTHER_SERVICE.useCounter(counter);
229
258
```
230
259
260
+
</TypeScriptExample>
261
+
231
262
Here, three different workers are involved:
232
263
233
264
1. The calling Worker (we'll call this the "introducer")
@@ -244,13 +275,42 @@ Currently, this proxying only lasts until the end of the Workers' execution cont
244
275
245
276
In this video, we explore how Cloudflare Workers support Remote Procedure Calls (RPC) to simplify communication between Workers. Learn how to implement RPC in your JavaScript applications and build serverless solutions with ease. Whether you're managing microservices or optimizing web architecture, this tutorial will show you how to quickly set up and use Cloudflare Workers for RPC calls. By the end of this video, you'll understand how to call functions between Workers, pass functions as arguments, and implement user authentication with Cloudflare Workers.
246
277
247
-
<Streamid="d506935b6767fd07626adbec46d41e6d"title="Introduction to Workers RPC"thumbnail="2.5s" />
278
+
<Stream
279
+
id="d506935b6767fd07626adbec46d41e6d"
280
+
title="Introduction to Workers RPC"
281
+
thumbnail="2.5s"
282
+
/>
248
283
249
284
## More Details
250
285
251
286
<DirectoryListing />
252
287
253
288
## Limitations
254
289
255
-
*[Smart Placement](/workers/configuration/smart-placement/) is currently ignored when making RPC calls. If Smart Placement is enabled for Worker A, and Worker B declares a [Service Binding](/workers/runtime-apis/bindings) to it, when Worker B calls Worker A via RPC, Worker A will run locally, on the same machine.
256
-
* The maximum serialized RPC limit is 1 MB. Consider using [`ReadableStream`](/workers/runtime-apis/streams/readablestream/) when returning more data.
290
+
-[Smart Placement](/workers/configuration/smart-placement/) is currently ignored when making RPC calls. If Smart Placement is enabled for Worker A, and Worker B declares a [Service Binding](/workers/runtime-apis/bindings) to it, when Worker B calls Worker A via RPC, Worker A will run locally, on the same machine.
291
+
292
+
- The maximum serialized RPC limit is 32 MiB. Consider using [`ReadableStream`](/workers/runtime-apis/streams/readablestream/) when returning more data.
293
+
294
+
<TypeScriptExample>
295
+
296
+
```ts
297
+
exportclassMyServiceextendsWorkerEntrypoint {
298
+
async foo() {
299
+
// Although this works, it puts a lot of memory pressure on the isolate.
300
+
// If possible, streaming the data from its original source is much preferred and would yield better performance.
301
+
// If you must buffer the data into memory, consider chunking it into smaller pieces if possible.
0 commit comments