Batching
Reduce API calls and database writes by processing many events in one run.
Group activity events by account and send one bulk write for each batch. Inngest collects matching events and passes them to one function run as events, reducing calls to your database or API.
batchEvents: { maxSize: 3, timeout: "4s" }- Event
- Collecting into a batch
- Step executing
- Completed
- Events in the batch
The first batch starts as soon as it holds three events. The second batch holds only two, so it starts when the 4s timeout expires. Each batch is one run that receives every event in it.
Create a batch
Set batchEvents.maxSize and batchEvents.timeout. This TypeScript v4 example groups events by account and handles up to five events per run. Replace the log call with your bulk API or database write.
import { Inngest } from "inngest";
const inngest = new Inngest({ id: "activity" });
export const recordActivity = inngest.createFunction(
{
id: "record-activity",
triggers: { event: "activity/recorded" },
batchEvents: {
maxSize: 5,
timeout: "5s",
key: "event.data.accountId",
},
},
async ({ events, step }) => {
const rows = events.map(({ data }) => ({
accountId: String(data.accountId),
action: String(data.action),
}));
return step.run("write-batch", async () => {
console.info(rows);
return rows.length;
});
}
);
Use events for every event in the batch. The singular event argument does not contain the full batch.
When the function starts
Inngest opens a batch when the first matching event arrives. It starts one run when the batch reaches maxSize, its timeout expires, or the combined event data reaches the 10 MiB hard cap. A batch can contain fewer than maxSize events.
The optional key is a Common Expression Language expression over each incoming event. Each distinct value gets its own batch. Use it to keep one account's events together. The optional if expression batches only events for which it evaluates to true. Events that do not match, or cannot produce a boolean result, run immediately.
batchEvents: {
maxSize: 5,
timeout: "5s",
key: "event.data.accountId",
if: 'event.data.plan == "free"',
}
Choose a batch size your handler can process within its memory and execution limits. Keep steps that write a whole batch safe to retry.
Combine with concurrency
You can use Step concurrency to cap how many batches execute together. For example, concurrency: { limit: 1 } lets only one batch from this function execute at a time.
If concurrency also uses a key, Inngest evaluates that key from the first event in the batch. Use the same key expression for batching and concurrency. Otherwise, a mixed batch can consume a slot for the first event's key even though it also contains events for other keys.
batchEvents: {
maxSize: 5,
timeout: "5s",
key: "event.data.accountId",
},
concurrency: {
limit: 1,
key: "event.data.accountId",
},
This configuration runs at most one batch per account at a time. Different accounts can use their own slots.
Features you cannot combine
Batching cannot be combined on the same function with idempotency, rate limiting, cancellation events, or priority. Debounce also cannot be combined with batching. Put work that needs an incompatible control in a separate function.
Plan limits
The pricing page is the source for current plan limits:
| Plan | Events in one batch | Maximum batch timeout |
|---|---|---|
| Free | 5 | 30 seconds |
| Pro | 100 | 5 minutes |
| Business | 500 | 5 minutes |
| Enterprise | Custom | Custom |
The 10 MiB batch size hard cap still applies. A batch starts when it reaches that cap, even if it has not reached maxSize or timeout.