--- title: Reliability | Vitable Docs description: Retry behavior, circuit breaker, delivery guarantees, and best practices. --- ## 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 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](mailto:felippe@vitablehealth.com) to re-enable a disabled endpoint after resolving the issue ## 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 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 - **Respond quickly** — return a `2xx` response as soon as possible, then process the event asynchronously. Long-running processing should happen in a background job. - **Be idempotent** — use `event_id` to 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-Signature` header before processing. - **Use HTTPS** — webhook endpoints must use HTTPS in production. - **Fetch fresh data** — after receiving an event, call the API with the `resource_id` to get the current state rather than relying on cached data.