Skip to main content

Retry Behaviour

amser retries failed webhook deliveries automatically. A delivery is considered failed if your endpoint returns a non-2xx HTTP status code or does not respond within the timeout window.

Retry Schedule

Failed deliveries are retried on an exponential backoff schedule:

AttemptDelay After Failure
1Immediate
25 minutes
330 minutes
42 hours
58 hours

After 5 total delivery attempts, the event is marked as permanently failed. No further automatic retries will occur.

info

The exact retry delays are subject to change. Design your webhook consumer to handle retries at any interval rather than relying on specific timing.

Timeout

amser waits up to 30 seconds for a response from your endpoint. If no response is received within 30 seconds, the delivery is treated as failed and enters the retry queue.

To avoid timeouts, respond with HTTP 200 immediately upon receiving the request. Perform any long-running work (database writes, API calls, email sends) asynchronously after sending the response.

Idempotency

Each event has a stable id field (a deterministic UUID v5, e.g. 550e8400-e29b-51d4-a716-446655440000). This ID does not change across retries.

Your webhook handler should use this ID to deduplicate events. A common pattern is to store processed event IDs in your database and skip any event you have already handled. This protects you from two scenarios:

  1. Retry after partial success — Your endpoint returned a 200 but crashed before completing all processing. amser does not retry in this case, but if it did not receive the 200 (e.g., the connection dropped), it will retry.
  2. Network-level duplication — In rare cases, infrastructure issues can cause a delivery to arrive more than once even when the first delivery succeeded.
async function processEvent(event: WebhookEvent) {
// Check if already processed
const existing = await db.webhookEvents.findById(event.id);
if (existing) {
return; // Already handled
}

// Process the event
await handleEvent(event);

// Mark as processed
await db.webhookEvents.insert({ id: event.id, processed_at: Date.now() });
}

Dashboard

Merchants can view webhook delivery history in the amser dashboard. The delivery log shows:

  • Event type and ID
  • HTTP status code returned by your endpoint
  • Delivery timestamp and response time
  • Number of attempts and current status (delivered, retrying, failed)

Individual events can be manually replayed from the dashboard. This is useful for recovering from extended outages or debugging integration issues.

Best Practices

  • Respond fast. Return HTTP 200 before doing any async work. This prevents timeouts and unnecessary retries.
  • Deduplicate by event ID. Store processed event IDs and check before handling. This makes your handler safe against retries and network-level duplicates.
  • Monitor delivery failures. Check the dashboard regularly for permanently failed deliveries. Persistent failures often indicate a misconfigured endpoint or a bug in your handler.
  • Handle out-of-order delivery. Events may arrive in a different order than they occurred, especially when retries are involved. Design your handler to be order-independent where possible, or use the created_at timestamp to sequence events.

Next Steps