diff --git a/pages/docs/examples/cleanup-after-function-cancellation.mdx b/pages/docs/examples/cleanup-after-function-cancellation.mdx
new file mode 100644
index 000000000..2e6b7a6c9
--- /dev/null
+++ b/pages/docs/examples/cleanup-after-function-cancellation.mdx
@@ -0,0 +1,114 @@
+import { ResourceGrid, Resource } from 'src/shared/Docs/Resources';
+
+import { RiBracesFill, RiErrorWarningFill } from "@remixicon/react";
+
+export const description = "Create a function that executes after a function run has been cancelled via event, REST API, or bulk cancellation.";
+
+# Cleanup after function cancellation
+
+When function runs are cancelled, you may want to perform some sort of post-cancellation code. This example will use the [`inngest/function.cancelled`](/docs/reference/system-events/inngest-function-cancelled) system event.
+
+Whether your function run is cancelled via [`cancelOn` event](/docs/features/inngest-functions/cancellation/cancel-on-events), [REST API](/docs/guides/cancel-running-functions) or [bulk cancellation](/docs/platform/manage/bulk-cancellation), this method will work the same.
+
+## Quick snippet
+
+Here is an Inngest function and a corresponding function that will be run whenever the original function is cancelled. This uses the function trigger's `if` parameter to filter the `inngest/function.cancelled` event to only be triggered for the original function.
+
+```ts
+const inngest = new Inngest({ id: "newsletter-app" });
+
+// This is our "import" function that will get cancelled
+export const importAllContacts = inngest.createFunction(
+ {
+ id: "import-all-contacts",
+ cancelOn: [{ event: "contacts/import.cancelled", if: "async.data.importId == event.data.importId" }]
+ },
+ { event: "contacts/import.requested" },
+ async ({ event, step }) => {
+ // This is a long running function
+ }
+)
+
+// This function will be run only when the matching function_id has a run that is cancelled
+export const cleanupCancelledImport = inngest.createFunction(
+ {
+ name: "Cleanup cancelled import",
+ id: "cleanup-cancelled-import"
+ },
+ {
+ event: "inngest/function.cancelled",
+ // The function ID is a hyphenated slug of the App ID w/ the functions" id
+ if: "event.data.function_id == 'newsletter-app-import-all-contacts'"
+ },
+ async ({ event, step, logger }) => {
+ // This code will execute after your function is cancelled
+
+ // The event that triggered our original function run is passed nested in our event payload
+ const originalTriggeringEvent = event.data.event;
+ logger.info(`Import was cancelled: ${originalTriggeringEvent.data.importId}`)
+ }
+);
+```
+
+An example cancellation event payload:
+
+```json
+{
+ "name": "inngest/function.cancelled",
+ "data": {
+ "error": {
+ "error": "function cancelled",
+ "message": "function cancelled",
+ "name": "Error"
+ },
+ "event": {
+ "data": {
+ "importId": "bdce1b1b-6e3a-43e6-84c2-2deb559cdde6"
+ },
+ "id": "01JDJK451Y9KFGE5TTM2FHDEDN",
+ "name": "contacts/import.requested",
+ "ts": 1732558407003,
+ "user": {}
+ },
+ "events": [
+ {
+ "data": {
+ "importId": "bdce1b1b-6e3a-43e6-84c2-2deb559cdde6"
+ },
+ "id": "01JDJK451Y9KFGE5TTM2FHDEDN",
+ "name": "contacts/import.requested",
+ "ts": 1732558407003,
+ "user": {}
+ }
+ ],
+ "function_id": "newsletter-app-import-all-contacts",
+ "run_id": "01JDJKGTGDVV4DTXHY6XYB7BKK"
+ },
+ "id": "01JDJKH1S5P2YER8PKXPZJ1YZJ",
+ "ts": 1732570023717
+}
+```
+
+## More context
+
+Check the resources below to learn more about building email sequences with Inngest.
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/docs/examples/track-failures-in-datadog.mdx b/pages/docs/examples/track-failures-in-datadog.mdx
index 583e1733e..07baeff8b 100644
--- a/pages/docs/examples/track-failures-in-datadog.mdx
+++ b/pages/docs/examples/track-failures-in-datadog.mdx
@@ -1,5 +1,4 @@
import { ResourceGrid, Resource } from 'src/shared/Docs/Resources';
-import { Example } from 'src/shared/Docs/Examples';
import { RiBracesFill, RiErrorWarningFill } from "@remixicon/react";
@@ -102,7 +101,7 @@ Check the resources below to learn more about building email sequences with Inng
diff --git a/pages/docs/features/inngest-functions/cancellation.mdx b/pages/docs/features/inngest-functions/cancellation.mdx
index ce92fa946..829ff8bb2 100644
--- a/pages/docs/features/inngest-functions/cancellation.mdx
+++ b/pages/docs/features/inngest-functions/cancellation.mdx
@@ -118,4 +118,10 @@ Let's now look at two different cancellations triggered from the Dashboard Bulk
-All canceled Function runs can be replay by using the Platform's [Functions Replay UI](/docs/platform/replay).
\ No newline at end of file
+All canceled Function runs can be replay by using the Platform's [Functions Replay UI](/docs/platform/replay).
+
+## Handling cancelled functions
+
+Function runs that are cancelled may require additional work like database cleanup or purging of deletion of temporary resources. This can be done leveraging the [`inngest/function.cancelled`](/docs/reference/system-events/inngest-function-cancelled) system event.
+
+See [this complete example](/docs/examples/cleanup-after-function-cancellation) for how to use this event within your system to cleanup after a function run is cancelled.
\ No newline at end of file
diff --git a/pages/docs/features/inngest-functions/error-retries/failure-handlers.mdx b/pages/docs/features/inngest-functions/error-retries/failure-handlers.mdx
index 737418860..9a4cda856 100644
--- a/pages/docs/features/inngest-functions/error-retries/failure-handlers.mdx
+++ b/pages/docs/features/inngest-functions/error-retries/failure-handlers.mdx
@@ -35,3 +35,6 @@ inngest.createFunction(
```
+
+ To handle cancelled function runs, checkout out [this example](/docs/examples/cleanup-after-function-cancellation) that uses the [`inngest/function.cancelled`](/docs/reference/system-events/inngest-function-cancelled) system event.
+
diff --git a/pages/docs/reference/system-events/inngest-function-cancelled.mdx b/pages/docs/reference/system-events/inngest-function-cancelled.mdx
new file mode 100644
index 000000000..1309d1731
--- /dev/null
+++ b/pages/docs/reference/system-events/inngest-function-cancelled.mdx
@@ -0,0 +1,101 @@
+import { Callout, CodeGroup, Properties, Property, Row, Col, VersionBadge } from "src/shared/Docs/mdx";
+
+# `inngest/function.cancelled` {{ className: "not-prose" }}
+
+The `inngest/function.cancelled` event is sent whenever any single function is cancelled in your [Inngest environment](/docs/platform/environments). The event will be sent if the event is cancelled via [`cancelOn` event](/docs/features/inngest-functions/cancellation/cancel-on-events), [REST API](/docs/guides/cancel-running-functions) or [bulk cancellation](/docs/platform/manage/bulk-cancellation).
+
+This event can be used to handle cleanup or similar for a single function or handle some sort of tracking function cancellations in some external system like Datadog.
+
+
+ You can write a function that uses the `"inngest/function.cancelled"` event with the optional `if` parameter to filter to specifically handle a single function by `function_id`.
+
+
+## The event payload
+
+
+
+
+
+
+ The `inngest/` event prefix is reserved for system events in each environment.
+
+
+ The event payload data.
+
+
+ Data about the error payload as returned from the cancelled function.
+
+
+ The cancellation error, always `"function cancelled"`
+
+
+ The name of the error, defaulting to `"Error"`.
+
+
+
+
+ The cancelled function's original event payload.
+
+
+ The cancelled function's [`id`](/docs/reference/functions/create#configuration).
+
+
+ The cancelled function's [run ID](/docs/reference/functions/create#run-id).
+
+
+
+
+ The timestamp integer in milliseconds at which the cancellation occurred.
+
+
+
+
+
+
+```json {{ title: "Example payload" }}
+{
+ "name": "inngest/function.cancelled",
+ "data": {
+ "error": {
+ "error": "function cancelled",
+ "message": "function cancelled",
+ "name": "Error"
+ },
+ "event": {
+ "data": {
+ "content": "Yost LLC explicabo eos",
+ "transcript": "s3://product-ideas/carber-vac-release.txt",
+ "userId": "bdce1b1b-6e3a-43e6-84c2-2deb559cdde6"
+ },
+ "id": "01JDJK451Y9KFGE5TTM2FHDEDN",
+ "name": "integrations/export.requested",
+ "ts": 1732558407003,
+ "user": {}
+ },
+ "events": [
+ {
+ "data": {
+ "content": "Yost LLC explicabo eos",
+ "transcript": "s3://product-ideas/carber-vac-release.txt",
+ "userId": "bdce1b1b-6e3a-43e6-84c2-2deb559cdde6"
+ },
+ "id": "01JDJK451Y9KFGE5TTM2FHDEDN",
+ "name": "integrations/export.requested",
+ "ts": 1732558407003
+ }
+ ],
+ "function_id": "demo-app-export",
+ "run_id": "01JDJKGTGDVV4DTXHY6XYB7BKK"
+ },
+ "id": "01JDJKH1S5P2YER8PKXPZJ1YZJ",
+ "ts": 1732570023717
+}
+```
+
+
+
+
+
+## Related resources
+
+* [Example: Cleanup after function cancellation](/docs/examples/cleanup-after-function-cancellation)
\ No newline at end of file
diff --git a/shared/Docs/navigationStructure.ts b/shared/Docs/navigationStructure.ts
index 096612183..57ed568e5 100644
--- a/shared/Docs/navigationStructure.ts
+++ b/shared/Docs/navigationStructure.ts
@@ -339,10 +339,15 @@ const sectionReference: NavGroup[] = [
title: "System events",
links: [
{
- title: "inngest/function.failed",
+ title: "function.failed",
href: "/docs/reference/system-events/inngest-function-failed",
className: "font-mono",
},
+ {
+ title: "function.cancelled",
+ href: "/docs/reference/system-events/inngest-function-cancelled",
+ className: "font-mono",
+ },
],
},
];
@@ -886,6 +891,10 @@ const sectionExamples: NavGroup[] = [
title: "Track all function failures in Datadog",
href: `/docs/examples/track-failures-in-datadog`,
},
+ {
+ title: "Cleanup after function cancellation",
+ href: `/docs/examples/cleanup-after-function-cancellation`,
+ },
],
},
];