Reliability
Retry behavior, circuit breaker, delivery guarantees, and best practices.
Retry Behavior
Section titled “Retry Behavior”If your endpoint doesn’t respond with a 2xx status code, Vitable retries delivery with exponential backoff:
| Parameter | Value |
|---|---|
| Maximum attempts | 14 |
| Backoff strategy | Exponential with jitter |
| First retry | 1 minute after failure |
| Maximum backoff | 24 hours |
| Total retry window | ~3.4 days |
After 14 failed attempts, the delivery is marked as permanently failed.
Circuit Breaker
Section titled “Circuit Breaker”If your endpoint consistently fails, Vitable stops sending webhooks to protect both systems:
- The circuit opens after 25 consecutive webhook delivery failures (not individual attempts)
- While the circuit is open, new events are not delivered to that endpoint
- Contact us to re-enable a disabled endpoint after resolving the issue
Delivery Guarantees
Section titled “Delivery Guarantees”At-least-once delivery — Vitable guarantees that every event will be delivered at least once. Your endpoint may receive duplicate events, so your processing logic must be idempotent. Use the event_id field to detect and handle duplicates.
Querying Missed Events
Section titled “Querying Missed Events”If your endpoint was down or you need to reprocess events, you can query the Vitable API for webhook events within a specific timeframe. This self-service approach lets you recover without contacting support.
Best Practices
Section titled “Best Practices”- Respond quickly — return a
2xxresponse as soon as possible, then process the event asynchronously. Long-running processing should happen in a background job. - Be idempotent — use
event_idto deduplicate. Your handler should produce the same result whether called once or multiple times with the same event. - Verify signatures — always validate the
X-Vitable-Signatureheader before processing. - Use HTTPS — webhook endpoints must use HTTPS in production.
- Fetch fresh data — after receiving an event, call the API with the
resource_idto get the current state rather than relying on cached data.