Buni.aiDocs
Automation
Automation

Automation best practices

Build automations that are safe to retry, respect provider rate limits, wait without holding resources and never process the same item twice.

Automations run unattended, often in bulk, and often in response to systems that retry. These practices keep them predictable.

Make runs safe to repeat

Webhook senders retry when they don't get a fast answer, and people double-click submit buttons. Design so that a second delivery of the same event does no harm.

  • Send an idempotency key. When you call a Webhook trigger from your own system, send an x-idempotency-key header with a stable id for the event, such as an order id. A repeat of a key the trigger has already accepted returns 200 with "deduplicated": true and does not start a run. Without the header, two identical requests both run, by design.
  • Rely on provider event ids. App triggers such as Stripe, GitHub, Shopify, Slack and Telegram deduplicate on the provider's own event id, so a redelivered event runs once.
  • Use Run once per entity where it fits. On the standard trigger node's External section, Enrollment Policy can be Run once per entity instead of Run on every matching event.
  • Check before you write. Before creating a record, read it with a Data Store GET on its lookup key and use a Router or Filter to skip records that already exist.
  • Use async mode for slow workflows. A Webhook trigger in Async (202) mode answers immediately, so the sender does not time out and retry while the run is still going.

Pace bulk sends

A Loop runs its body as fast as it can by default. When the body calls a provider with a rate limit, set Pacing:

PacingSettingsUse for
No pacing (default)NoneInternal steps with no external limit.
Even pacingMaximum per secondProviders with a published per-second cap. WhatsApp's Cloud API, for example, allows 80 calls per second.
Batch pauseItems per batch, Pause (ms)Providers that allow a burst followed by a cool-off.

Pacing applies to one run: two runs at the same time each get their own pace. If you trigger many runs at once, the combined rate is higher than one run's setting.

Also set Max iterations on every loop over external data, so a bad payload with a huge list cannot run away.

For sends to a list, choose Carry on, then report under If an item fails, so one bad number does not stop everyone else's message. See Error workflows.

Wait instead of polling

To do something later (a reminder tomorrow, a follow-up in three days), use a Wait node with a Duration and Unit (Milliseconds to Days). The wait is durable: the run pauses as Waiting and resumes on time, even when the wait is days long.

Don't build waits out of loops that check the time, and don't use a schedule that runs every minute to look for work that a Wait could have scheduled directly.

Remove duplicates before you act

When a list can contain repeats (the same phone number twice in an import, say), add a Remove Duplicates node before the loop:

  • Source variable: the list, for example state.results
  • Compare by field (optional): the field that identifies an item, for example phone. Leave it blank to compare whole items.
  • Keep: First occurrence or Last occurrence
  • Output variable: the de-duplicated list

Avoid trigger loops

A workflow that writes to the thing that triggers it can start itself forever.

  • A Data Store trigger ignores records written by workflow runs by default (Ignore workflow writes). Leave that on unless you have a reason not to.
  • An Error trigger never reacts to failures of error-handler runs.
  • For Webhook triggers, don't have the workflow call its own trigger URL.

Stop early

Put a Filter near the start of the workflow to drop events you don't care about. A Filter whose condition is false ends the run quietly, without counting as a failure, so later nodes never spend time or money on it.

Test before you publish

  • Use the Run panel or a trigger's test URL; both run the draft and never touch the published version.
  • Turn off Include test runs on Error triggers, so test failures don't page anyone.
  • Keep API keys and tokens in Credentials, never typed into node fields.
  • Publish only when the test run's trace looks right, then watch the first production runs in the Activity tab.
Last reviewed 24 September 2026

On this page