diff --git a/src/content/changelog/workers/2025-05-22-handle-request-cancellation.mdx b/src/content/changelog/workers/2025-05-22-handle-request-cancellation.mdx
new file mode 100644
index 00000000000000..89205f2b639ab6
--- /dev/null
+++ b/src/content/changelog/workers/2025-05-22-handle-request-cancellation.mdx
@@ -0,0 +1,18 @@
+---
+title: Handle incoming request cancellation in Workers with Request.signal
+description: Workers can now add event listeners on Request.signal and perform tasks when the request is cancelled by the client
+products:
+ - workers
+date: 2025-05-22T01:00:00Z
+---
+
+import { Render } from "~/components";
+
+In Cloudflare Workers, you can now attach an event listener to [`Request`](/workers/runtime-apis/request/) objects, using the [`signal` property](https://developer.mozilla.org/en-US/docs/Web/API/Request/signal). This allows you to perform tasks when the request to your Worker is canceled by the client. To use this feature, you must set the [`enable_request_signal`](/workers/configuration/compatibility-flags/#enable-requestsignal-for-incoming-requests) compatibility flag.
+
+You can use a listener to perform cleanup tasks or write to logs before your Worker's invocation ends. For example, if you run the Worker below, and then abort the request from the client, a log will be written:
+
+
+
+
+For more information see the [`Request` documentation](/workers/runtime-apis/request).
diff --git a/src/content/compatibility-flags/request-signal.md b/src/content/compatibility-flags/request-signal.md
new file mode 100644
index 00000000000000..e60e43e66403e2
--- /dev/null
+++ b/src/content/compatibility-flags/request-signal.md
@@ -0,0 +1,8 @@
+---
+name: "Enable `Request.signal` for incoming requests"
+sort_date: "2025-05-22"
+enable_flag: "enable_request_signal"
+disable_flag: "disable_request_signal"
+---
+
+When you use the `enable_request_signal` compatibility flag, you can attach an event listener to [`Request`](/workers/runtime-apis/request/) objects, using the [`signal` property](https://developer.mozilla.org/en-US/docs/Web/API/Request/signal). This allows you to perform tasks when the request to your Worker is canceled by the client.
\ No newline at end of file
diff --git a/src/content/docs/workers/runtime-apis/request.mdx b/src/content/docs/workers/runtime-apis/request.mdx
index 93f4cb620f56af..0571113efb32b4 100644
--- a/src/content/docs/workers/runtime-apis/request.mdx
+++ b/src/content/docs/workers/runtime-apis/request.mdx
@@ -6,7 +6,7 @@ description: Interface that represents an HTTP request.
---
-import { Type, MetaInfo } from "~/components";
+import { Type, MetaInfo, Render } from "~/components";
The [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request) interface represents an HTTP request and is part of the [Fetch API](/workers/runtime-apis/fetch/).
@@ -88,6 +88,8 @@ An object containing properties that you want to apply to the request.
* The redirect mode to use: `follow`, `error`, or `manual`. The default for a new `Request` object is `follow`. Note, however, that the incoming `Request` property of a `FetchEvent` will have redirect mode `manual`.
+* `signal` AbortSignal optional
+ * If provided, the request can be canceled by triggering an abort on the corresponding `AbortController`.
#### The `cf` property (`RequestInitCfProperties`)
@@ -194,6 +196,11 @@ All properties of an incoming `Request` object (the request you receive from the
* The redirect mode to use: `follow`, `error`, or `manual`. The `fetch` method will automatically follow redirects if the redirect mode is set to `follow`. If set to `manual`, the `3xx` redirect response will be returned to the caller as-is. The default for a new `Request` object is `follow`. Note, however, that the incoming `Request` property of a `FetchEvent` will have redirect mode `manual`.
+* `signal` AbortSignal read-only
+ * The `AbortSignal` corresponding to this request. If you use the [`enable_request_signal`](/workers/configuration/compatibility-flags/#enable-requestsignal-for-incoming-requests) compatibility flag, you can attach an event listener to the signal. This allows you to perform cleanup tasks or write to logs before your Worker's invocation ends.
+ For example, if you run the Worker below, and then abort the request from the client, a log will be written:
+
+
* `url` string read-only
* Contains the URL of the request.
diff --git a/src/content/partials/workers/request-signal-example.mdx b/src/content/partials/workers/request-signal-example.mdx
new file mode 100644
index 00000000000000..e07caed0427765
--- /dev/null
+++ b/src/content/partials/workers/request-signal-example.mdx
@@ -0,0 +1,35 @@
+---
+{}
+
+---
+
+import { TypeScriptExample } from "~/components";
+
+
+```ts
+export default {
+ async fetch(request, env, ctx): Promise {
+ // This sets up an event listener that will be called if the client disconnects from your
+ // worker.
+ request.signal.addEventListener('abort', () => {
+ console.log('The request was aborted!');
+ });
+
+ const { readable, writable } = new IdentityTransformStream();
+ sendPing(writable);
+ return new Response(readable, { headers: { 'Content-Type': 'text/plain' } });
+ },
+} satisfies ExportedHandler;
+
+async function sendPing(writable: WritableStream): Promise {
+ const writer = writable.getWriter();
+ const enc = new TextEncoder();
+
+ for (;;) {
+ // Send 'ping' every second to keep the connection alive
+ await writer.write(enc.encode('ping\r\n'));
+ await scheduler.wait(1000);
+ }
+}
+```
+