惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
Y
Y Combinator Blog
T
Tailwind CSS Blog
G
Google Developers Blog
博客园 - Franky
Google DeepMind News
Google DeepMind News
阮一峰的网络日志
阮一峰的网络日志
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 聂微东
爱范儿
爱范儿
博客园 - 【当耐特】
腾讯CDC
T
The Blog of Author Tim Ferriss
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
C
Check Point Blog
大猫的无限游戏
大猫的无限游戏
M
MIT News - Artificial intelligence
博客园_首页
Stack Overflow Blog
Stack Overflow Blog
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Supabase Webhooks Deep Dive — Database Triggers, pg_net &...
kanta13jp1 · 2026-05-03 · via DEV Community

kanta13jp1

Supabase Webhooks Deep Dive — Database Triggers, pg_net & Edge Function Patterns

Supabase Webhooks let you react to INSERT/UPDATE/DELETE events on any table and call an external endpoint or an Edge Function automatically. Under the hood it uses the pg_net extension to fire non-blocking HTTP requests directly from PostgreSQL triggers.

How it works

DB change → pg_net (async HTTP) → Edge Function or external endpoint

Enter fullscreen mode Exit fullscreen mode

Configuring via Dashboard

  1. Database → Webhooks → Create a new hook
  2. Select table and events (INSERT / UPDATE / DELETE)
  3. Provide an endpoint URL
  4. Set HTTP method and headers

Controlling pg_net directly in SQL

create extension if not exists pg_net;

-- Fire a POST from within a SQL function
select net.http_post(
  url := 'https://your-project.supabase.co/functions/v1/notify-user',
  body := json_build_object(
    'user_id', NEW.user_id,
    'event', 'new_message'
  )::jsonb,
  headers := '{"Authorization": "Bearer <service-role-key>",
               "Content-Type": "application/json"}'::jsonb
);

Enter fullscreen mode Exit fullscreen mode

Pattern: send a welcome email on user sign-up

create or replace function public.handle_new_user()
returns trigger language plpgsql security definer as $$
begin
  perform net.http_post(
    url := current_setting('app.settings.supabase_url')
           || '/functions/v1/send-welcome-email',
    body := json_build_object(
      'user_id', NEW.id,
      'email', NEW.email,
      'display_name', NEW.raw_user_meta_data->>'display_name'
    )::jsonb,
    headers := json_build_object(
      'Authorization', 'Bearer '
        || current_setting('app.settings.service_role_key'),
      'Content-Type', 'application/json'
    )::jsonb
  );
  return NEW;
end;
$$;

create trigger on_auth_user_created
  after insert on auth.users
  for each row execute procedure public.handle_new_user();

Enter fullscreen mode Exit fullscreen mode

Scheduled jobs with pg_cron

create extension if not exists pg_cron;

-- Delete expired sessions every night at 00:00 UTC
select cron.schedule(
  'cleanup-expired-sessions',
  '0 0 * * *',
  $$delete from user_sessions where expires_at < now();$$
);

-- Flag overdue WBS tasks every hour
select cron.schedule(
  'check-overdue-wbs-tasks',
  '0 * * * *',
  $$
    update wbs_tasks set status = 'overdue'
    where deadline < now()
      and status not in ('completed', 'overdue');
  $$
);

Enter fullscreen mode Exit fullscreen mode

Webhook security — HMAC signature verification

export async function verifyWebhookSignature(
  req: Request,
  secret: string
): Promise<boolean> {
  const signature = req.headers.get("x-supabase-webhook-signature");
  if (!signature) return false;

  const body = await req.text();
  const key = await crypto.subtle.importKey(
    "raw",
    new TextEncoder().encode(secret),
    { name: "HMAC", hash: "SHA-256" },
    false,
    ["sign"]
  );
  const sig = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(body));
  const expected =
    "sha256=" +
    Array.from(new Uint8Array(sig))
      .map((b) => b.toString(16).padStart(2, "0"))
      .join("");

  return signature === expected;
}

Enter fullscreen mode Exit fullscreen mode

Retry failed webhooks automatically

create table if not exists webhook_logs (
  id bigint generated always as identity primary key,
  event_type text not null,
  payload jsonb not null,
  response_status int,
  retry_count int default 0,
  created_at timestamptz default now()
);

-- Retry every 5 minutes, up to 3 attempts
select cron.schedule('retry-failed-webhooks', '*/5 * * * *', $$
  select net.http_post(
    url := 'https://your-project.supabase.co/functions/v1/process-event',
    body := payload,
    headers := '{"Content-Type":"application/json"}'::jsonb
  )
  from webhook_logs
  where response_status >= 500
    and retry_count < 3
    and created_at > now() - interval '24 hours';
$$);

Enter fullscreen mode Exit fullscreen mode

Real-world usage at Jibun K.K.

  • Auto-post to X on achievement insertpost-x-update EF called via Database Webhook
  • WBS overdue detectionpg_cron flags tasks hourly and triggers Slack notification
  • AI University sitemap update — fires when a new provider is inserted into ai_university_providers

Quick reference

Scenario Tool
DB change → external service Database Webhooks (Dashboard)
DB change → Edge Function pg_net.http_post in trigger
Scheduled batch pg_cron.schedule
Webhook auth HMAC SHA-256 signature check

With Webhooks and pg_cron combined, you can automate entire backend workflows without touching a single line of frontend code.