All posts
No-Code & Tools

Supabase Database Webhook Not Firing? Debug pg_net Before Rewriting Your App

A boundary-first way to diagnose Supabase Database Webhooks that appear to fire but never reach your application.

Elvis Onunwa16 September 20266 min readLast updated: 16 September 2026
Supabase Database Webhook Not Firing? Debug pg_net Before Rewriting Your App

TL;DR

  • A successful row change does not prove the webhook reached your endpoint because Supabase Database Webhooks use asynchronous pg_net requests.
  • Check the trigger and pg_net worker before changing application code.
  • Use the net response history to separate transport failures from endpoint HTTP errors.
  • If the endpoint receives the request, only then debug authentication, payload handling and business logic.
On this page⌄

When a Supabase Database Webhook appears to do nothing, do not begin by rewriting the Edge Function or webhook handler.

First answer a more useful question: how far did the event actually travel?

A Database Webhook crosses several boundaries:

row change → database trigger → pg_net worker → HTTP request → receiving endpoint → authentication → handler logic → downstream side effect

A failure at any one of those points can look identical from the product UI. The user clicks Save, the database row changes, and the expected email, payment update, notification or automation never happens.

That is why I prefer boundary-first debugging for webhook systems. Find the last layer that definitely worked before changing code downstream.

1. Confirm the database event actually matches the webhook

Start with the boring checks because they eliminate a surprising amount of wasted debugging.

Supabase Database Webhooks can be attached to INSERT, UPDATE and DELETE events. Confirm the webhook is attached to the correct table and that the operation you are testing is one of the enabled events.

Supabase’s current Database Webhooks documentation explains that these webhooks are implemented as database triggers and use the pg_net extension for asynchronous HTTP requests.

That architecture has an important implication: the database mutation succeeding does not prove the remote action succeeded.

The row can be committed while the outbound HTTP request fails later.

If you are building payments, booking flows, onboarding or notification systems, do not model “database row saved” and “external side effect completed” as the same state.

2. Check whether the pg_net worker is alive

If the trigger exists but nothing appears to leave the database, inspect the worker before touching your application.

Supabase’s current webhook debugging guide recommends checking pg_stat_activity for the pg_net background worker:

select pid
from pg_stat_activity
where backend_type ilike '%pg_net%';

If that returns no worker PID, your receiving endpoint is not yet the main suspect.

For supported pg_net versions, Supabase documents net.worker_restart() as a way to restart the worker. Check the current documentation and your installed version before making infrastructure changes.

This is exactly the kind of failure an AI coding assistant can misdiagnose. If you tell it only “my webhook stopped working,” it may confidently rewrite the Edge Function even though the request never left Postgres.

3. Inspect the HTTP response history

Once you know pg_net is active, inspect what happened to outbound requests.

Supabase documents recent webhook response information in the net schema. Its troubleshooting guide uses net._http_response to find failed HTTP responses and transport errors.

A useful diagnostic query is:

select *
from net._http_response
where status_code >= 400
   or error_msg is not null
order by created desc;

Do not treat every failure in that result the same way.

Evidence Likely boundary
No relevant request/response evidence Trigger, worker or queue path
Timeout or connection error Network or endpoint reachability
401/403 Endpoint authentication/authorization
404 Wrong URL, route or deployment
500 Receiver executed but failed
2xx but side effect missing Handler logic or downstream system

The point is not the exact status code. The point is to stop debugging layers you have already proved are healthy.

4. Test the network path separately from your real handler

If you cannot tell whether pg_net itself can make outbound requests, test that boundary independently.

Supabase’s troubleshooting guide demonstrates sending a request to an echo endpoint with net.http_post() and then inspecting the response by request ID. That isolates the database networking layer from your own application code.

If a neutral endpoint works but your production endpoint fails, move your investigation toward DNS, TLS, firewall rules, routing, endpoint availability or authentication.

If the neutral request also fails, rewriting your business logic is unlikely to help.

5. Do not use localhost incorrectly in local development

Local webhook testing has a networking trap.

When Supabase runs locally, Postgres is inside Docker. localhost or 127.0.0.1 from that container refers to the container itself, not automatically to the web server running on your computer.

Supabase’s Database Webhooks documentation recommends host.docker.internal for reaching a service on the host in the common local setup.

So this:

http://localhost:3000/webhook

may fail even while the endpoint works perfectly in your browser.

That is a network-addressing problem, not an Edge Function bug.

6. If the request arrives, then inspect authentication

Once endpoint logs prove the request arrived, move to the auth boundary.

This matters particularly now because Supabase has introduced newer publishable and secret API keys alongside legacy keys. Its current API-key migration guide documents specific handling for pg_net and Database Webhooks, including differences between legacy bearer-key patterns and newer secret keys.

Do not blindly copy an old webhook header configuration into a new project.

Also avoid hardcoding privileged credentials in SQL or configuration where they can be exposed unnecessarily. Follow the current Supabase guidance for server-side secrets and Vault where appropriate.

If your webhook calls an Edge Function and receives a 401, use my separate guide on diagnosing Supabase Edge Function 401 errors. A 401 is a much narrower problem than “webhooks are broken.”

7. Verify the payload shape before blaming the database

Supabase’s documented webhook payload differs by operation.

An insert contains the new row in record. An update contains both record and old_record. A delete has record: null and puts the deleted row in old_record.

A handler that assumes payload.record always exists can therefore receive the webhook correctly and still fail on deletes.

Log enough metadata to answer:

  • which event type arrived;
  • which table produced it;
  • whether record or old_record is expected;
  • whether authentication passed;
  • whether the handler reached its downstream action;
  • whether that action succeeded.

Do not log secrets or sensitive payload fields just to make debugging easier.

8. Treat webhooks as a delivery system, not proof of business completion

The deeper production lesson is about state.

Suppose an order row changes to paid and a webhook is expected to create an invoice. If the webhook fails, the database may say the order is paid while the invoice is still missing.

For important workflows, model those facts separately.

For example:

payment confirmed
invoice pending
invoice generated
invoice delivery pending
invoice delivered

That gives you something observable and recoverable instead of one optimistic boolean pretending several distributed operations happened together.

It also makes retries safer. Before retrying a side effect, determine whether the first attempt partially succeeded. Payments, emails, receipts and external API calls should be designed with idempotency in mind where the downstream system supports it.

A practical debugging order

When a Supabase Database Webhook stops working, use this sequence:

  1. Confirm the table and INSERT/UPDATE/DELETE event.
  2. Confirm the trigger exists.
  3. Confirm the pg_net worker is active.
  4. Inspect recent net responses and errors.
  5. Test outbound HTTP independently if necessary.
  6. Confirm the endpoint URL and reachability.
  7. Confirm the request appears in receiver logs.
  8. Then inspect authentication and headers.
  9. Validate the payload shape.
  10. Trace the downstream side effect and its state.

That order protects the evidence you need to diagnose the problem.

If you are preparing an AI-built product for real users, also work through my AI-built app production checklist. Webhook reliability is one example of the gap between a feature that works in a demo and a workflow that can be operated safely in production.

If your Supabase or AI-built MVP has reached the point where failures cross database, auth, function and payment boundaries, see my MVP development service or contact me. I can help trace the system before a small integration bug becomes a rewrite.

Frequently asked questions

Questions, answered.

Why is my Supabase Database Webhook not firing?

The failure can be at the trigger, pg_net worker, network request, endpoint authentication or handler logic. Check those boundaries in order instead of rewriting the receiver first.

Where can I see failed Supabase Database Webhook requests?

Supabase documents webhook call history under the net schema, including net._http_response for recent responses and errors.

Why does my Supabase webhook work remotely but not on localhost?

In local Supabase, Postgres runs inside Docker, so localhost points back to the container. Supabase recommends host.docker.internal or an appropriate host address for a locally running receiver.

NEED HELP WITH THE BUILD?

Turn what you learned here into a clearer website or MVP.

Share the goal, current stage, and constraints. I’ll help you identify the smallest responsible next step.

Continue reading

Related notes.