How to Test Supabase Webhooks Locally
What Webhooks Does Supabase Send?
Supabase provides two types of webhook functionality: database webhooks (triggers that fire HTTP requests on INSERT, UPDATE, or DELETE operations) and auth webhooks (for custom auth logic). Database webhooks are built on PostgreSQL triggers and the pg_net extension, allowing you to fire an HTTP request whenever a row changes in any table.
Database webhook payloads include the type (INSERT, UPDATE, or DELETE), the table name, schema, record (the new row for INSERT/UPDATE), and old_record (the previous row for UPDATE/DELETE). This gives you a complete picture of what changed and what the data looked like before and after.
Auth webhooks allow you to customize authentication behavior. The send_sms hook lets you use a custom SMS provider, the send_email hook customizes email delivery, and the custom_access_token hook lets you modify the JWT claims. These are configured in the Supabase Dashboard under Authentication > Hooks.
Setting Up Supabase Database Webhooks
In the Supabase Dashboard, go to Database > Webhooks and click "Create a new hook." Select the table and events (INSERT, UPDATE, DELETE) you want to monitor. For the HTTP request, enter your ReqPour URL as the endpoint.
You can also create database webhooks using SQL:
create trigger my_webhook_trigger
after insert or update or delete on public.orders
for each row
execute function supabase_functions.http_request(
'https://abc123.reqpour.com/supabase',
'POST',
'{"Content-Type": "application/json"}',
'{}',
'5000'
);Once configured, insert a row into the table and watch the webhook appear in the ReqPour dashboard. The payload shows the new record and the operation type. Start the relay to forward these events to your local server:
npx reqpour relay --to http://localhost:3000/api/webhooks/supabaseHandling Supabase Database Webhooks
Here is a handler for Supabase database webhook events:
app.post('/api/webhooks/supabase', express.json(), (req, res) => {
const { type, table, record, old_record } = req.body; console.log(${type} on ${table});
switch (type) { case 'INSERT': console.log('New record:', record); // Sync to external system, send notification, etc. if (table === 'orders') { sendOrderConfirmation(record); } break;
case 'UPDATE': console.log('Updated from:', old_record, 'to:', record); if (table === 'orders' && record.status !== old_record.status) { notifyStatusChange(record.id, record.status); } break;
case 'DELETE': console.log('Deleted record:', old_record); cleanupRelatedData(old_record.id); break; }
res.status(200).send('OK'); }); ```
The old_record field is only present for UPDATE and DELETE operations. For INSERT, only record is populated. This gives you the full before/after picture for updates, which is useful for change detection logic.
Auth Webhooks and Edge Functions
Supabase auth webhooks intercept authentication flows. For example, the custom_access_token hook fires before a JWT is issued, letting you add custom claims:
// Supabase Edge Function handling custom_access_token hook
Deno.serve(async (req) => {
const payload = await req.json();
const { user_id, claims } = payload;// Add custom claims based on user data const role = await getUserRole(user_id); claims.user_role = role;
return new Response(JSON.stringify({ claims }), { headers: { 'Content-Type': 'application/json' }, }); }); ```
During development, point auth hooks at your ReqPour endpoint to inspect the payloads and understand what data is available. Then use the relay to forward to your local Edge Function emulator for testing your custom logic.
The ReqPour dashboard is particularly useful for auth webhooks because you can see exactly what claims are being requested and returned, which helps debug JWT-related issues in your application.
Supabase Webhook Tips
Database webhooks fire within the same transaction as the triggering operation. If your webhook endpoint is slow or unreachable, it can delay the database operation. During development, ReqPour handles this by responding quickly, so your database operations are not affected.
For production, consider using Supabase Edge Functions or a message queue between the webhook and your processing logic. This decouples database performance from webhook handler latency. During development with ReqPour, you can simulate slow handlers using the dashboard's timing information.
Supabase database webhooks do not include built-in signature verification. If you need to verify that requests come from your Supabase project, include a secret in the webhook headers configuration and check it in your handler. The ReqPour dashboard shows all headers, making it easy to verify your secret header is being sent correctly.
Related
Get started with ReqPour
Catch, inspect, and relay webhooks to localhost. Free to start, $3/mo for Pro.