← Back to documentation

Retries and Delivery Behavior

Configure webhook retries and understand automatic retries for other target types.

9 min read

Use this guide to configure the retries and to read the delivery outcomes.

Purpose#

This guide covers:

  • The retry configuration for each webhook destination.
  • The automatic retry behavior for a Slack, Discord, email, Microsoft Teams, PagerDuty, Telegram, and Google Sheets target.
  • The plan retry limits for all the delivery types.
  • The Activity outcomes of a failed delivery.
  • Idempotent handling for a receiver. Idempotent handling gives the same result when an event arrives again.

How retries operate#

You configure the retries for each destination, and not for each endpoint.

Webhook targets#

  • Set Delivery retries for each webhook destination in the Outputs tab.
  • PayloadRelay uses the fixed schedule of the selected retry preset.
  • The default is 0. There are no retries.
  • Your plan tier sets the limit for the effective retries.

Plan retry caps:

PlanMax retries
Sandbox1
Team trial5
Solo3
Team5
Scale5

If a webhook retry count is more than the plan limit, the API rejects the configuration.

The webhook retry schedule depends on the retry preset of each destination. For the schedules, see Webhook Retry Presets.

Default preset (STANDARD) schedule:

RetryDelay
130 seconds
22 minutes
310 minutes
430 minutes
51 hour

PayloadRelay uses only the delays that the configured retry count needs. Sandbox and Solo use STANDARD with the default retry status codes. On the Team trial, Team, Scale, and an eligible custom plan, you can select an advanced preset or a custom status-code filter.

Slack and Discord targets#

A Slack target and a Discord target use the automatic retry schedule below. You cannot change this schedule. Sandbox uses a maximum of 1 retry, Solo uses a maximum of 3, and the Team trial, Team, and Scale use a maximum of 5. For a custom plan, the agreement of the organization sets the retry limit.

RetryDelay
11 second
22 seconds
35 seconds
410 seconds
530 seconds

Email, Microsoft Teams, PagerDuty, and Telegram targets#

An email, Microsoft Teams, PagerDuty, and Telegram target uses the automatic retry schedule below. You cannot change this configuration. Sandbox uses a maximum of 1 retry, Solo uses a maximum of 3, and the Team trial, Team, and Scale use a maximum of 5. For a custom plan, the agreement of the organization sets the retry limit.

RetryDelay
130 seconds
22 minutes
310 minutes
430 minutes
51 hour

An email retry applies to a temporary provider error. A permanent SMTP error, such as an authentication error and an SMTP 5xx recipient rejection, fails immediately. A Microsoft Teams, PagerDuty, and Telegram retry applies to a network error, HTTP 408, HTTP 429, and a 5xx response.

Google Sheets targets#

Google Sheets retries a temporary error with the automatic schedule below. The plan limit and the 24-hour message age limit apply. You cannot change this configuration. Sandbox uses a maximum of 1 retry, Solo uses a maximum of 3, and the Team trial, Team, and Scale use a maximum of 5. For a custom plan, the agreement of the organization sets the retry limit.

RetryDelay
130 seconds
22 minutes
310 minutes
430 minutes
51 hour

A Google Sheets retry applies only to an error that PayloadRelay can retry, such as a rate limit, a server error, and a connection error. PayloadRelay does not retry a Google Sheets API error such as 400 or 403.

Duplicate rows on retry

Google Sheets delivery is at-least-once, in the same way as all the other target types. The Google Sheets API has no idempotency key for a row that it adds. If Google accepts a row and the response is lost because of a timeout or a worker restart, the retry adds the row again. The API cannot prevent this result.

If you need exactly-once rows, put a stable event identifier in the payload. Put it in a spreadsheet column, and deduplicate on that value, for example, with a helper column or a pivot. PayloadRelay reads row 1 before each delivery, and a deduplication column that you add manually stays.

Row order

PayloadRelay adds the rows in the delivery order. This is usually the send order, but PayloadRelay does not guarantee it. PayloadRelay reschedules a delivery that needs a retry, and a delivery that waits for the per-account rate limit of Google. That delivery can come after the later rows. This is most visible above approximately 60 rows in one minute for one Google account, which is the Google limit.

A delivery that only this rate limit holds back does not use a retry attempt. The delivery did not fail. PayloadRelay tries it again later. The wait increases from seconds to minutes, and it can increase to one hour after some hours in the queue. If the traffic stays above the Google limit, the rows arrive late and in a different order. PayloadRelay abandons a delivery only after 24 hours.

A test delivery uses a different rule. If the account is at the Google limit, PayloadRelay reports an unsent test as failed after approximately two minutes. It does not keep the test in the queue.

To build the original order again, put a timestamp or a sequence number in the payload. Put it in its own column, and sort on that column instead of the row position.

Failover behavior#

Failover gives a backup delivery path when the primary webhook destination is not available. It is available on a webhook destination only.

How failover operates

  1. The primary webhook destination attempts the delivery, with all the configured retries.
  2. If the delivery uses all the retries and still fails, PayloadRelay sends the request to the configured failover destination.
  3. Activity records the failover delivery with the outcome FAILOVER_TRIGGERED.
  4. If the failover destination is a webhook destination, it has its own independent retry value. A supported failover destination that is not a webhook (email, Slack, Discord, Microsoft Teams) uses its standard automatic retry schedule, in the limit of your plan.

Configuring failover

  1. Open the endpoint edit page and open the Outputs tab.
  2. Expand the webhook destination that needs a failover.
  3. Select Enable failover delivery.
  4. Select a failover destination in the list. The supported failover delivery destinations are webhook, email, Slack, Discord, and Microsoft Teams. PayloadRelay does not support a Google Sheets, PagerDuty, or Telegram target for a failover.
  5. If it is necessary, configure the failover fields, such as the email subject or the Slack Markdown control.
  6. Save the endpoint.

Failover behavior notes

  • The failover starts only after the primary destination uses all its retries. If the webhook has 0 retries, the failover starts after the first error.
  • Activity records the FAILOVER_TRIGGERED outcome separately from the primary delivery attempt, and you can see the two rows.
  • If the primary delivery and the failover delivery fail, there is no more fallback. The final outcome stays DELIVERY_FAILED.
  • A test delivery from the Send test button never starts a failover. The failover applies to production traffic only.
Example: Webhook with email failover
Incoming request
  Primary webhook output → fails after 3 retries
  Email failover destination → delivers to [email protected]

This pattern sends the real-time webhook first. If it is not available, the email path receives the event.

Example: Webhook with another webhook failover
Incoming request
  Primary webhook (api.example.com) → fails after retries
  Failover webhook output (backup.example.com) → has its own 2 retries

Use this pattern when the two destinations are webhooks, and the failover must also retry independently.

Before you start#

  • Edit access to the endpoint.
  • Access to the Billing page, to read the plan limits.
  • Access to Activity, to monitor the outcomes.

Procedure#

1. Read the plan retry cap#

  1. Open Billing.
  2. Read the delivery retry limit of the tier.

2. Configure webhook retries#

  1. Open the endpoint edit page.
  2. Open the Outputs tab.
  3. For each webhook destination, set Delivery retries in the plan range.
  4. Save.

A target with no retry configuration for the user (email, Slack, Discord, Microsoft Teams, PagerDuty, Telegram, and Google Sheets) retries automatically when PayloadRelay supports it, in the limit of your plan.

The retries, the failover, and the fan-out consume no more accepted-event quota.

3. Monitor outcomes#

In Request activity, monitor these outcomes:

  • DELIVERY_FAILED: the delivery failed after all the retries.
  • FAILOVER_TRIGGERED: the failover destination started after the primary webhook used all its retries.
  • TEST_REJECTED and TEST_RATE_LIMITED: the outcomes of a target test only.

4. Make downstream handling idempotent#

A receiver must accept a repeated delivery:

  • If a stable event identifier is available, deduplicate with it.
  • Make the writes idempotent.
  • Prevent a side effect that fails when an event arrives again.

This also applies at the first acceptance. A successful acceptance response does not mean that every destination delivered the event. If PayloadRelay returns a temporary error, send the original event again, and deduplicate at each receiver with your own stable event key.

PayloadRelay does not store a customer relay request body or a customer message body in its databases, activity logs, object storage, or backups. A body stays only in memory and in the delivery, retry, and dead-letter queues. It stays there only while PayloadRelay delivers the event. If the delivery fails permanently, the message stays in a dead-letter queue for a maximum of 7 days for diagnosis or a new delivery. PayloadRelay can keep operational metadata, such as an SMTP envelope sender address, in the 30-day Activity trail.

Expected result#

  • The webhook retry values agree with the plan limits.
  • A target that is not a webhook retries automatically with no configuration.
  • Activity shows the delivery errors.
  • Activity records a failover with the FAILOVER_TRIGGERED outcome.
  • A downstream system processes a repeated delivery safely.

Common issues and fixes#

  • PayloadRelay rejects the retry value: make the value equal to the plan maximum or lower.
  • Frequent DELIVERY_FAILED: make sure that the destination authentication, the connectivity, and the TLS are correct.
  • Unexpected duplicates downstream: add idempotency controls.
  • The failover does not start: make sure that the failover is enabled on the webhook destination. Make sure that the request is production traffic. Make sure that the primary delivery failed or used all its retries.