Cancel running functions

With Inngest, your functions can be running or paused for long periods of time. You may have function with hundreds of steps, or you may be using step.sleep, step.sleepUntil, or step.waitForEvent. Sometimes, things happen in your system that make it no longer necessary to complete running the function, which is when cancelling is necessary.

In this guide, you'll learn how to cancel running functions in two ways:

Cancel with events

As you have learned that you can trigger functions to run using events, you can also cancel active functions by sending an event.

For our example, we'll take a reminder app where a user can schedule to be reminded of something in the future at whatever time they want. The user can also delete the reminder if they change their mind and don't want to receive the reminder anymore.

Delaying code to run for days or weeks is easy with step.sleepUntil, but we need a way to be able to stop the function if the user deletes the reminder while our function is "sleeping."

When defining a function, you can also specify the cancelOn option which allows you to list one or more events that, when sent to Inngest, will cause the sleep to be terminated and function will be marked as "Canceled."

Here is our schedule reminders function that leverages cancelOn:

inngest/syncContacts.ts

const scheduleReminder = inngest.createFunction(
  {
    id: "schedule-reminder",
    cancelOn: [{
      event: "tasks/reminder.deleted", // The event name that cancels this function
      // Ensure the cancelation event (async) and the triggering event (event)'s reminderId are the same:
      if: "async.data.reminderId == event.data.reminderId",
    }],
  }
  { event: "tasks/reminder.created" },
  async ({ event, step }) => {
    await step.sleepUntil('sleep-until-remind-at-time', event.data.remindAt);
    await step.run('send-reminder-push', async ({}) => {
      await pushNotificationService.push(event.data.userId, event.data.reminderBody)
    })
  }
  // ...
);

Let's break down how this works:

  1. Whenever the function is triggered, a cancelation listener is created which waits for an "tasks/reminder.deleted" event to be received.
  2. The if statement tells Inngest that both the triggering event ("tasks/reminder.created") and the cancelation event ("tasks/reminder.deleted") have the same exact value for data.reminderId in each event payload. This makes sure that an event does not cancel a different reminder.

For more information on writing events, read our guide on writing expressions.

Here is an example of these two events which will be matched on the data.reminderId field:

{
  "name": "tasks/reminder.created",
  "data": {
    "userId": "user_123",
    "reminderId": "reminder_0987654321",
    "reminderBody": "Pick up Jane from the airport"
  }
}
{
  "name": "tasks/reminder.deleted",
  "data": {
    "userId": "user_123",
    "reminderId": "reminder_0987654321",
  }
}

Tips

  • You can also optionally specify a timeout to only enable cancelation for a period of time.
  • You can configure multiple events to cancel a function, up to five.
  • You can write a more complex matching statement using the if field.

Learn more in the full reference.

Bulk cancel via the REST API

You can also cancel functions in bulk via the REST API. This is useful if you have a large number of functions within a specific range that you need to cancel.

With the POST /cancellations endpoint, you can cancel functions by specifying the app_id, function_id, and a started_after and started_before timestamp range. You can also optionally specify an if statement to only cancel functions that match a given expression.

POST
api.inngest.com/v1/cancellations
curl -X POST https://api.inngest.com/v1/cancellations \
  -H 'Authorization: Bearer signkey-prod-<YOUR-SIGNING-KEY>' \
  -H 'Content-Type: application/json' \
  --data '{
    "app_id": "acme-app",
    "function_id": "schedule-reminder",
    "started_after": "2024-01-21T18:23:12.000Z",
    "started_before": "2024-01-22T14:22:42.130Z",
    "if": "event.data.userId == 'user_o9235hf84hf'"
  }'

When successful, the response will be returned with the cancellation ID and the cancellation job data:

Response

{
  "id": "01HMRMPE5ZQ4AMNJ3S2N79QGRZ",
  "environment_id": "e03843e1-d2df-419e-9b7b-678b03f7398f",
  "function_id": "schedule-reminder",
  "started_after": "2024-01-21T18:23:12.000Z",
  "started_before": "2024-01-22T14:22:42.130Z",
  "if": "event.data.userId == 'user_o9235hf84hf'"
}

To learn more, read the full REST API reference.