Skip to content

Hooks (Before & After)

Hooks let you attach edge function logic to database mutations. There are two types:

Hook TypeTimingExecutionUse Cases
Before hookBefore the DB mutationSynchronous — can block or modifyValidation, enrichment, business rule enforcement
After hookAfter successful DB mutationAsynchronous — non-blockingNotifications, analytics, cascade actions

A before hook is called synchronously by pulsabase-core before the SQL query is executed. The hook receives the incoming payload and can:

  • Allow the operation (return normally)
  • Block the operation (return an error or non-2xx status)
  • (Future) Modify the payload before it hits the database
  • Enforce business rules beyond what RLS can express (e.g., “a user can only be in 5 rooms”)
  • Validate computed fields that span multiple tables
  • Block mutations outside business hours or maintenance windows
  1. Go to Dashboard → Edge Functions → Hooks
  2. Click New Hook
  3. Select Before as the hook type
  4. Choose the target table and action (INSERT, UPDATE, or DELETE)
  5. Select the edge function to invoke
Function: check-room-limit
Step 1: get_count → [Database]
SELECT COUNT(*) as count FROM room_members WHERE user_id = {{jwt.sub}}
Step 2: check → [Condition]
{{steps.get_count.body.count}} >= 5
If TRUE → return { "error": "MAX_ROOMS_REACHED", "status": 400 }
If FALSE → continue (allow the INSERT)

When a user tries to join a 6th room, the before hook returns a 400 response and the INSERT is never executed.

An after hook is triggered asynchronously via NATS after a successful database mutation. The original operation completes immediately — the hook runs in the background.

  • Send a notification when a new message is inserted
  • Update a materialized view or a denormalized counter
  • Log to an external analytics system
  • Trigger a cascade delete on an external service
  1. Go to Dashboard → Edge Functions → Hooks
  2. Click New Hook
  3. Select After as the hook type
  4. Choose the target table and action
  5. Select the edge function to invoke
Hook: after INSERT on messages
Function: notify-room-members
Step 1: get_members → [Database]
SELECT user_id FROM room_members WHERE room_id = {{input.room_id}}
Step 2: send → [HTTP]
POST https://push.example.com/notify
Body: { "users": {{steps.get_members.body}}, "message": "New message in {{input.room_name}}" }

By default, edge functions invoked via hooks run asynchronously (after hooks) or synchronously (before hooks). When you invoke a function directly via the SDK, you can explicitly choose:

// Synchronous invocation — waits for the full result
const result = await pb.edge('check-room-limit').invoke({ userId, roomId });
// Async invocation — fire and forget, does not wait for result
await pb.edge('send-welcome-email').invokeAsync({ userId });