BetterBase provides an event-driven webhook system for notifying external services when database changes occur.
- Event Types - INSERT, UPDATE, DELETE triggers
- Signed Payloads - HMAC signatures for verification
- Retry Logic - Automatic retry with exponential backoff
- Filtering - Trigger webhooks on specific conditions
- Logs - View delivery history and status
Define webhooks in betterbase.config.ts:
export default defineConfig({
webhooks: [
{
id: 'user-notifications',
table: 'users',
events: ['INSERT', 'UPDATE'],
url: process.env.USER_WEBHOOK_URL,
secret: process.env.USER_WEBHOOK_SECRET,
enabled: true
},
{
id: 'order-events',
table: 'orders',
events: ['INSERT', 'UPDATE', 'DELETE'],
url: process.env.ORDER_WEBHOOK_URL,
secret: process.env.ORDER_WEBHOOK_SECRET
}
]
}){
"event": "INSERT",
"table": "users",
"record": {
"id": "user-123",
"name": "John Doe",
"email": "john@example.com",
"createdAt": "2024-01-15T10:30:00Z"
},
"old_record": null,
"timestamp": "2024-01-15T10:30:00Z"
}| Field | Description |
|---|---|
event |
Event type: INSERT, UPDATE, DELETE |
table |
Database table name |
record |
New/updated record |
old_record |
Previous record (UPDATE/DELETE only) |
timestamp |
ISO timestamp |
Webhooks include an X-Webhook-Signature header:
import { createHmac } from 'crypto'
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
const expectedSignature = createHmac('sha256', secret)
.update(payload)
.digest('hex')
return signature === expectedSignature
}
// In your webhook handler
app.post('/webhook', async (c) => {
const payload = await c.req.text()
const signature = c.req.header('X-Webhook-Signature')
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return c.json({ error: 'Invalid signature' }, 401)
}
const event = JSON.parse(payload)
// Process the event
})webhooks: [
{
id: 'important-events',
table: 'orders',
events: ['INSERT'],
url: process.env.ORDER_WEBHOOK_URL,
secret: process.env.ORDER_WEBHOOK_SECRET,
retry: {
maxAttempts: 5,
retryInterval: 1000, // Start at 1 second
maxInterval: 30000 // Cap at 30 seconds
}
}
]Retry behavior:
- Exponential backoff between attempts
- Failed deliveries logged for review
- Manual retry available via CLI
# List webhooks
bb webhook list
# Test a webhook
bb webhook test user-notifications
# View webhook logs
bb webhook logs user-notifications
# View recent logs
bb webhook logs user-notifications -l 50Trigger webhooks manually:
import { triggerWebhook } from '@betterbase/core/webhooks'
await triggerWebhook({
id: 'custom-event',
table: 'orders',
event: 'INSERT',
record: newOrder,
timestamp: new Date().toISOString()
})- Verify signatures - Always verify webhook signatures
- Respond quickly - Acknowledge receipt immediately
- Queue processing - Process events asynchronously
- Idempotent handlers - Handle duplicate events
- Log everything - Track all webhook activity
# Webhook URLs and secrets
USER_WEBHOOK_URL=https://hooks.example.com/user
USER_WEBHOOK_SECRET=your-webhook-secret
ORDER_WEBHOOK_URL=https://hooks.example.com/orders
ORDER_WEBHOOK_SECRET=your-order-secret- Configuration - Webhook config
- Functions - Process webhooks with functions
- CLI Commands - Webhook CLI