Skip to main content
sajn records every event before it delivers it, then queues one delivery for each endpoint that subscribes to the event type. A delivery is one event sent to one endpoint, and it’s made of one or more attempts. Deliveries usually leave within seconds of the event. If queueing fails, a background sweep picks the event up again within about a minute, so an event isn’t lost because of a problem on the sajn side.

Successful and failed attempts

An attempt succeeds when your endpoint returns a 2xx status code within 30 seconds. Anything else fails, and sajn retries it: sajn retries 4xx codes because a receiver that’s being deployed often answers 404 Not Found or 401 Unauthorized for a few minutes. To tell sajn that the endpoint is gone for good, return 410 Gone. To move an endpoint, update its URL instead of redirecting. sajn also checks the URL’s address before each attempt; a host that has started to resolve to a private address fails as a network error.

Retry schedule

sajn makes up to 12 attempts over about three days. The wait between attempts grows sixfold each time, up to 12 hours: Every attempt carries the same event id in the body and in webhook-id, so a receiver that deduplicates on it processes the event once. Each attempt has its own webhook-timestamp and signature. Each attempt also uses the endpoint’s API version and signing secret at the time of the attempt, so if you change apiVersion while a delivery is being retried, the next attempt has the new shape. After the last attempt, the delivery is FAILED. To send it again, retry it within 7 days.

Slow sajn down

To slow sajn down, return 429 Too Many Requests with a Retry-After header, in seconds or as an HTTP date. sajn holds back every delivery to that endpoint until that time, and then sends them. Without a valid Retry-After header, sajn waits 60 seconds. The 429 response uses up one attempt of that delivery; the deliveries that sajn holds back don’t use up attempts.

Errors on the sajn side

If a delivery can’t run because of a problem on the sajn side, sajn reschedules it every 5 minutes for up to 24 hours. These reschedules don’t use up attempts.

Ordering and duplicates

sajn doesn’t deliver events in order. Deliveries run in parallel, and a retried delivery can arrive after an event that happened later. To decide which update is newest, compare the events’ createdAt, or read the resource from the API when the order matters. For example, store createdAt with each record that an event updates, and skip an event whose createdAt is older. Delivery is at least once, so the same event can arrive more than once, for example when your endpoint processed it but timed out before it answered. Store each event id that you’ve processed, for at least as long as the retry window, and skip the ones you’ve seen.

Delivery log

sajn logs every delivery with all its attempts, and keeps the log for 7 days. Read it in the dashboard under Inställningar > Utvecklare > Loggar, or through the API: A delivery is similar to the following:
The request body and headers in this example are shortened. A delivery has the following fields: sajn ignores your response body; it only stores it for the log, up to 64 KB, and cuts a response that isn’t JSON to its first 1,000 characters. Keep your responses short.

Automatic pausing

When an endpoint keeps failing, sajn pauses it and stops sending to it. sajn pauses an endpoint in either of the following cases:
  • The endpoint returns 410 Gone.
  • Every attempt to the endpoint has failed for 72 hours, with at least 5 failed attempts in a row. This is about when the first delivery of the streak runs out of attempts.
One successful attempt ends the streak, so an endpoint that answers some events with 2xx and fails others isn’t paused. Endpoints that an integration installed are never paused, because the integration manages its own endpoint. While an endpoint is paused, its status is PAUSED, pausedAt is the time of the pause, and pauseReason is the last answer, such as HTTP_410 or NETWORK_ERROR. sajn doesn’t send it anything. Each new event appears in the delivery log as a FAILED delivery with one attempt numbered 0, and stays there for 7 days. sajn also notifies you. To resume deliveries, fix your endpoint and then reactivate it. Reactivating doesn’t resend the events from the pause. To deliver them, retry each delivery, or process them from the events API, as Replay and reconcile events describes.