Last updated

Retries & reliability

Jeeves delivers events with at-least-once semantics. Your handler must be idempotent.

Automatic retries

If your endpoint does not return 2xx in time, Jeeves retries with exponential back-off:

AttemptDelay after previous failure
1st (initial delivery)Immediate
2nd retry2 minutes
3rd retry30 minutes

After all retries are exhausted the delivery is marked exhausted. You can still trigger a manual retry.

What triggers a retry

  • HTTP 5xx
  • HTTP 429 — Jeeves honors the Retry-After header if set
  • Network errors: connection refused, DNS failure, connection timeout

Retries are NOT triggered by: 2xx (success) or other 4xx (treated as permanent failures).

Concurrency limit

Jeeves caps each subscription at 5 concurrent in-flight requests. If you need to back off further, return 429 with a Retry-After header.

Manual retries

POST /v1/webhooks/events/{eventId}/retry
  • Re-delivers the event to every active subscription subscribed to its type
  • One-shot — a failed manual retry does not trigger another automatic retry
  • Returns 409 if any active subscription still has an in-flight delivery for this event

Circuit breaker

After 50 consecutive failed deliveries, a subscription is automatically set to disabled and an alert email is sent to every address in developerEmail. Re-enable once your endpoint is healthy:

PATCH /v1/webhooks/subscriptions/{id}
{ "status": "active" }

The consecutive-failure counter resets after the first successful delivery.

Idempotency

Use X-Webhook-Event-Id (or the envelope id) as a unique constraint in your database. A reliable pattern:

-- Pseudocode
INSERT INTO processed_events (event_id, processed_at)
VALUES (:event_id, NOW())
ON CONFLICT (event_id) DO NOTHING;

IF rows_affected == 0:
    return  -- already processed — skip

-- safe to apply business logic