Batch function

Learn more about the batch workflow function within Knock's notification engine.

A batch function collects notifications that have to do with the same subject, so you can send fewer notifications to your users.

Batch functions are helpful when a recipient needs to be notified about a lot of activity happening at once, but doesn't need a notification for every single activity within the batch. Commenting is a common use case. If a user leaves ten comments in a page in fifteen minutes, you don't want to send the user ten separate notifications. You want to send them one notification about the ten comments they just received.

How batching works

Here's a step-by-step breakdown of how a batch function works:

  • When a given per-recipient workflow run hits a batch step, the batch function will stay open for an interval of time which you define (the batch window).
  • While that interval is open, the batch function aggregates any additional incoming triggers for that recipient. If a batch key is provided in your batch step, the incoming triggers for that recipient will be grouped into separate batches based on batch key.
  • When the batch window interval closes, the workflow continues to the next step, with the data collected in the batch available in the workflow run scope. You can read more in the "using batch variables" section of this guide.
🌠
By default the batch will only return the first (or last) 10 items to be rendered in your template. This limit can be configured on our Enterprise Plan (up to 100 items). The batch can, however, accumulate any number of items over the window that it's open.

Selecting a batch key

A batch function always batches incoming notifications per recipient. If you do not provide a batch key, your batch function will just batch per recipient. If you do provide a batch key, your batch function will batch by recipient and then by your batch key. A batch key resolves to a value in your data payload by which to group incoming notifications.

🌠
A quick tip. Here's a helpful way to think about batching. By default the batch function batches on a key of recipient_id. When a batch key is provided, it batches on a key of concat(recipient_id, batch_key).

As an example, in a document editing app where a recipient is receiving notifications about activity across different pages, you can provide a batch key of page_id and the user will receive different batch notifications about each page that was included in the batch.

Using the batch function to batch new comment notifications by page.

Using the batch function to batch new comment notifications by page.

Here's a detailed walkthrough of how this example might work in practice:

  • You have a new-comment workflow that includes a batch step.
  • You send six trigger calls to that workflow: three about page A and three about page B. The trigger calls are all for the same recipient Elmo.
  • If your batch step does not have a batch key, Elmo will receive a batched notification about six activities.
  • If your batch step includes a batch key of page_id, Elmo will receive two notifications: one for the three activities about page A and one for the three activities about page B.

Setting the batch window

The batch window determines the length of time that the batch will be open, with the window opening from the first time the batch is triggered.

Set a fixed batch window

You can set a fixed duration batch window using the "Batch for a fixed window" option in the batch step. The window accepts a relative duration, which can be specified in seconds, minutes, hours, or days.

The batch is opened when it is first triggered for a given recipient. The batch is closed after the fixed duration of time has elapsed.

Set a dynamic batch window using a variable

You can also set the length of your batch windows dynamically using a variable. You can use any of the data, recipient, actor, or environment variables associated with the workflow run to retrieve your dynamic batch window.

When specifying a dynamic batch window you must provide one of the following:

  • An ISO-8601 timestamp (e.g. 2022-05-04T20:34:07Z) which must be a datetime in the future
  • A relative duration (e.g { "unit": "seconds", "value": 30 })
  • A window rule (e.g { "frequency": "daily", "hours": 9, "minutes": 30 })

A dynamic window must be available to be resolved via the key you specify on the given schema, meaning that if you specify a key of batchWindow in your data schema, your workflow trigger data must contain either an ISO-8601 timestamp, a valid duration unit, or a valid window rule.

When the key specified is missing or resolves to an invalid value, a corresponding error will be logged on the workflow run, and the batch will be skipped.

Please note: an open batch window will never be extended by a subsequent workflow trigger with a different dynamic batch window specified. Once a given batch has been opened by a workflow trigger, its window interval is immutable.

When the key specified is missing, or resolves to an invalid value, a corresponding error will be logged on the workflow run and the batch will be skipped.

Using a sliding batch window

By default, all batch windows are fixed, where the closing of the batch window is determined by the first trigger that starts the batch. In some situations, you may wish to "extend" the batch window when a new trigger is received to recompute the closing time of the batch. This option is supported in the batch step as a "sliding window."

When a sliding window is enabled on a batch function, subsequent workflow triggers that are detected by the already-open batch window will add the configured default window duration onto the already-open batch window. Let's walk through an example:

  • 🎛️ [Initial batch window: 1 minute]
  • Trigger: the batch opens with a closing window of now() + 1 min
  • ⏲️ [30 seconds pass]
  • Trigger: new item added to the batch, the closing window is recomputed to be now() + 1 min, a total of 1 minute and 30 seconds from when the batch was opened
  • ⏲️ [1 minute passes]
  • The batch closes after 1 minute and 30 seconds

Setting a maximum batch window duration

When using a sliding batch window, you must set an extension limit for the batch. This value represents the maximum amount of time that a batch window can remain open if it is extended by subsequent workflow triggers. This "Max window limit" option is displayed once you enable a sliding window by selecting "Extend window when new activities are received," and can be set as any duration unit.

Once configured, Knock will compute the maximum extended batch window for subsequent triggers as the time your batch was initially opened plus the maximum window duration. For example:

  • 🎛️ [Initial batch window: 12 hours]
  • 🎛️ [Max extension limit: 24 hours]
  • Trigger: the batch opens with a closing window of now() + 12 hrs
  • ⏲️ [6 hours pass]
  • Trigger: new item added to the batch, the closing window is recomputed to be now() + 12 hrs, a total of 18 hours from when the batch was opened
  • ⏲️ [Another 7 hours pass]
  • Trigger: new item added to the batch, the closing window is recomputed to be now() + 12 hrs, which would be a total of 25 hours. Because this exceeds the maximum extension limit, the window is set to close 24 hours after it was opened
  • ⏲️ [Another 3 hours pass]
  • Trigger: new item added to the batch. The closing window is not recomputed because the maximum extension has already been reached
  • ⏲️ [Another 8 hours pass]
  • The batch closes after 24 hours

If you configure your maximum window with a value that is less than the initial window duration, subsequent batched triggers will shorten the overall window. If this new maximum duration has already elapsed, the batch window will immediately close and the workflow run will proceed.

  • 🎛️ [Initial batch window: 24 hours]
  • 🎛️ [Max extension limit: 12 hours]
  • Trigger: the batch opens with a closing window of now() + 24 hrs
  • ⏲️ [23 hours pass]
  • Trigger: new item added to the batch, the closing window is recomputed to be now() + 24 hrs, a total of 47 hours from when the batch was opened. This exceeds the configured maximum of 12 hours, so the window is set to close 12 hours after it was opened
  • Because 12 hours have already elapsed, the batch window closes immediately (after 23 hours have elapsed)

To avoid confusion, we recommend always choosing a max extension limit duration that is greater than your initial batch window duration.

Setting the maximum activity limit

Optionally, you can also set a maximum limit for the number of activities allowed to be accumulated in a given batch, at anywhere between 2 and 1000 activities.

When this option is set, your batch window will close as soon as the number of activities accumulated in the batch reaches the maximum limit set, regardless of the amount of time remaining in its fixed or sliding batch window.

Setting the batch order

Although batches will accumulate every activity added to the batch, only ten items will be returned in activities once the batch step window closes. There are two options for which ten activity objects will be returned when the batch step closes:

  • The first ten (default): The ten oldest activity objects added to the batch step will be returned.
  • The last ten: The ten newest activity objects added to the batch will be returned.

Note that for both settings, the activities variable will always be sorted in chronological order (oldest to most recent).

Immediately flushing the first item in a batch

Batch steps optionally support a mode to immediately flush the first item in a batch. This mode is useful when you want to immediately notify a user about the first item in a batch, and then accumulate additional items over a window of time.

To enable this mode, you can toggle on "Immediately flush leading item" in the "Advanced settings" section of the batch step.

When this mode is enabled, the first item for an unopened batch will "open" the batch and the usual batching rules will apply. However, unlike a normal batch, the first item will not be included in the activities of the batch and will instead continue execution past the batch step.

If you want to branch on whether the first item in a batch was flushed or not, you can use the total_activities variable to do so. When it is set to 1, you know that you're working with the first item in a batch.

💡
Please note: if there is never a second item added to the batch, the batch will noop on closing as there is nothing in it to execute.

Working with batches in your templates

Another important aspect of batch functions is that they generate state that can be used in your templates. Let's continue the commenting example we used above.

In this scenario, we'll want different copy in our notification for when a batch includes one item ("Jane left a comment") v. when a batch includes more than one item ("Jane left n comments").

We can address use cases like this by referencing the total_activities variable within our workflow. Here's an example of a message template that uses this variable to determine what type of copy to use:

Here's a list of the variables that you can use to work with batch-related state.

  • total_activities. The number of activities included within the batch. (An example: In the notification "Dennis Nedry left 8 comments for you", the total_activities count equals eight).

  • total_actors. The number of unique actors that triggered activities included within the batch. (An example: In the notification "Dennis Nedry and two others left comments for you", the total_actors count equals three, Dennis plus the two others you mentioned in the notification).

  • activities. A list of up to ten of the activity objects included within the batch, where each activity equals the state sent across in your trigger call. The activities variable lists the first or last ten activity objects added to the batch (configurable by setting the batch order). Each activity includes any data properties you sent along in the trigger call, as well as any user properties for your actor and recipient(s). You can use the activities variable to create templates like this:

  • actors. A list of up to ten of the unique actors included within the batch, where each actor is a user object with the properties available on your Knock user schema. The actors variable lists the first or last ten actors added to the batch.

Setting the batch render limit (beyond 10)

Enterprise plan feature. The render limit setting for batch activities and actors is only available on our Enterprise plan.

By default, up to ten items will be returned in activities and actors variables inside your templates after the batch window closes.

On the Enterprise plan, you can configure the maximum number of activities and actors to be rendered in your templates beyond the default limit of 10, to any number between 2 and 100.

Using workflow cancellation with batches

If you want to remove an item from a batch (example: a user deletes a comment), you can use our workflow cancellation API to cancel a batched item, thereby removing it from the batch.

Important: Once a batch window has been opened, it will remain open until its full duration has elapsed. Any workflow cancellation will remove the specific individual workflow run that it references from the batch.

Because of this behavior, it's important to remember that canceling a workflow run that opened a batch window will never close the batch window itself. Any subsequent triggers to that recipient/workflow key combination will add activities to the open batch, and those activities will proceed when the batch window closes if their respective workflow runs are not also canceled. See the FAQs below for a workaround to close an open batch window.

Frequently asked questions