Webhook Best Practices
Follow these patterns to build reliable, secure, and maintainable webhook integrations.
Respond Quickly
Webhook providers expect a fast response. If your processing takes more than a few seconds, accept the webhook immediately and process it asynchronously.
Do this:
// Accept the webhook, process later
app.post('/webhook', async (req, res) => {
await queue.enqueue(req.body);
res.status(200).json({ received: true });
});Don't do this:
// Blocks the response until processing completes
app.post('/webhook', async (req, res) => {
await processOrder(req.body); // 10+ seconds
await updateInventory(req.body); // 5+ seconds
await notifyCustomer(req.body); // 3+ seconds
res.status(200).json({ done: true });
});Hookbase enforces a 30-second timeout. Destinations that consistently time out will trigger circuit breaker protection.
Implement Idempotency
Webhooks may be delivered more than once due to retries, network issues, or provider behavior. Your handler should produce the same result whether it processes an event once or multiple times.
Use Event IDs
Most providers include a unique event ID. Store processed IDs and skip duplicates:
app.post('/webhook', async (req, res) => {
const eventId = req.headers['x-hookbase-event-id'];
// Check if already processed
const exists = await db.get('SELECT 1 FROM processed_events WHERE event_id = ?', eventId);
if (exists) {
return res.status(200).json({ duplicate: true });
}
// Process and record
await processEvent(req.body);
await db.run('INSERT INTO processed_events (event_id) VALUES (?)', eventId);
res.status(200).json({ processed: true });
});Hookbase Deduplication
Hookbase can deduplicate events at the platform level before they reach your destination. Enable deduplication on your source to filter out duplicates automatically.
Verify Signatures
Always verify webhook signatures to ensure the payload hasn't been tampered with. Hookbase verifies signatures on inbound webhooks automatically, but you should also verify the delivery signature from Hookbase to your destination.
import crypto from 'crypto';
function verifyHookbaseSignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
app.post('/webhook', (req, res) => {
const signature = req.headers['x-hookbase-signature'];
if (!verifyHookbaseSignature(req.rawBody, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process webhook...
});TIP
Use crypto.timingSafeEqual() to prevent timing attacks when comparing signatures.
Handle Retries Gracefully
Hookbase retries failed deliveries with exponential backoff. Design your handler to work well with retries:
- Return proper status codes — Use
200-299for success,4xxfor permanent errors (won't retry),5xxfor temporary errors (will retry) - Be idempotent — Same event processed twice should have the same outcome
- Log the attempt — Include the
x-hookbase-delivery-idheader in your logs for tracing
| Response Code | Hookbase Behavior |
|---|---|
200-299 | Success, no retry |
400-499 | Permanent failure, no retry |
500-599 | Temporary failure, will retry |
| Timeout | Will retry |
| Connection error | Will retry |
Use Transforms to Simplify Handlers
Instead of parsing complex provider payloads in your application, use transforms to extract only the fields you need:
{
"event": type,
"customer_email": data.object.customer_email,
"amount": data.object.amount_total / 100,
"currency": data.object.currency
}This reduces your handler complexity and keeps your application code focused on business logic.
Apply Filters to Reduce Noise
Don't process webhooks you don't need. Use filters to only deliver relevant events:
type in ["checkout.session.completed", "invoice.paid", "customer.subscription.deleted"]Filtering at the platform level reduces load on your application and keeps your event processing focused.
Monitor Delivery Health
Set Up Notification Channels
Configure notification channels to alert you when:
- Delivery failure rate exceeds a threshold
- A destination becomes unreachable
- The circuit breaker opens
Track Key Metrics
Use the Analytics API to monitor:
- Delivery success rate — Should stay above 99%
- Average delivery latency — Watch for increasing trends
- Queue depth — Growing queues indicate destination problems
- Error distribution — Identify the most common failure modes
Check Health Status
Poll the Health API from your monitoring system to detect platform-level issues early.
Secure Your Webhooks
Use HTTPS Destinations
Always use https:// URLs for your destinations. Hookbase rejects http:// destinations in production to prevent payload interception.
Restrict Source IPs
Configure IP filtering to only accept webhooks from known provider IP ranges. Most providers publish their webhook IP ranges.
Enable Field Encryption
For sensitive data (PII, payment details), enable field-level encryption to encrypt specific fields before storage and delivery.
Rotate Secrets Regularly
Rotate your signing secrets periodically using the Sources API:
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/sources/{src_id}/rotate-secret \
-H "Authorization: Bearer whr_your_api_key"Update the new secret in your provider's dashboard immediately after rotation.
Plan for Failure
Configure Failover Destinations
Set up failover destinations so webhooks are delivered to a backup endpoint if your primary destination goes down.
Use the Dead Letter Queue
Events that exhaust all retry attempts land in the dead letter queue. Monitor the DLQ and set up a process to review and reprocess failed events.
Test Your Error Handling
Simulate failures during development:
- Return
500from your destination to test retries - Shut down your destination to test circuit breaker behavior
- Send malformed payloads to test your validation
Production Readiness Checklist
Before going live, verify:
- [ ] Signature verification is enabled on all sources
- [ ] Destinations use HTTPS
- [ ] Handlers are idempotent
- [ ] Handlers respond within 30 seconds
- [ ] Notification channels are configured for failures
- [ ] Failover destinations are set up for critical routes
- [ ] IP filtering is configured where applicable
- [ ] Secrets are stored securely (not hardcoded)
- [ ] Monitoring dashboards are in place
See the Production Readiness guide for a comprehensive checklist.
See Also
- Quick Start — Set up your first webhook pipeline
- Troubleshooting — Diagnose common issues
- Production Readiness — Full launch checklist
- Enterprise Security — Advanced security features