This section helps you understand different behaviors to expect regarding how Featurebase sends events to your webhook endpoint.
If a webhook delivery fails, Featurebase will automatically retry up to 3 times:
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute after the first attempt |
| 2nd retry | 1 hour after the second attempt |
| 3rd retry | 6 hours after the third attempt |
A delivery is considered failed if:
- Your endpoint returns a non-2xx status code
- The request times out
- A connection cannot be established
Featurebase doesn't guarantee that webhook events arrive in the order they were generated. For example, updating a post might generate the following sequence of events:
post.createdpost.updated
However, these events may not be delivered to your endpoint in that exact order. Your integration should not rely on receiving events sequentially, and it must be able to handle them regardless of arrival sequence.
Webhook endpoints might occasionally receive the same event more than once. To prevent double-processing, log the unique event IDs that your endpoint has already handled. If a new incoming event's ID matches a previously processed event, skip it.
{
"object": "notification_event",
"topic": "post.updated",
"id": "notif_0193a6e6-fb6b-78ef-b71f-15008d9f9cde"
}const processedEvents = new Set();
function handleWebhook(payload) {
// Check if we've already processed this event
if (processedEvents.has(payload.id)) {
console.log(`Skipping duplicate event: ${payload.id}`);
return;
}
// Mark as processed
processedEvents.add(payload.id);
// Process the event
processEvent(payload);
}Note: In production, you should persist processed event IDs to a database rather than keeping them in memory.
Your endpoint should return a successful (2xx) status code promptly—before performing any lengthy operations that might lead to timeouts.
Return 200 immediately, then process:
app.post("/webhook", async (req, res) => {
// 1. Return 200 OK right away
res.status(200).send("OK");
// 2. Process the webhook asynchronously
processWebhookEvent(req.body).catch((err) => {
console.error("Webhook processing error:", err);
});
});Wait for processing before responding:
app.post("/webhook", async (req, res) => {
// Don't do this - it could timeout
await processWebhookEvent(req.body);
res.status(200).send("OK");
});This approach prevents timeouts and ensures Featurebase knows your endpoint received the event, even if processing takes longer.
Your webhook can have one of the following statuses:
| Status | Description |
|---|---|
active | Webhook is functioning normally |
paused | Webhook is manually paused by you |
suspended | Webhook has been automatically suspended due to repeated failures |
If your webhook is suspended due to failures, you can reactivate it from your dashboard or via the Webhooks API after fixing the underlying issue.