Docs Services Sign In
Backend logic

Hooks

Hooks run logic when a record changes — without you writing a custom endpoint. Send a welcome email when a user signs up, keep a running total when an order is paid, or reject a write that breaks a business rule. They're declared in hooks.yaml and attached to a table and an event.

After-hooks

on_insert, on_update, and on_delete fire after a successful mutation and run asynchronously, so they never slow the response. Each hook can run SQL, send an email, fire an outbound webhook, or drop an in-app notification.

hooks.yaml
on_insert:
  contacts:
    - email:
        to: ""
        subject: "Welcome"
        template: "welcome"
    - notify: ""
      title: "Contact created"

on_update:
  orders:
    - sql: "UPDATE stats SET total = total + "
      when: "status = 'paid' AND old_status != 'paid'"

Before-hooks

before_insert, before_update, and before_delete run synchronously and can abort the mutation. Use them to enforce invariants the database alone can't — the request fails with a 422 and the row is never written.

hooks.yaml
before_insert:
  orders:
    - sql: "SELECT CASE WHEN amount > 10000
              THEN RAISE(ABORT, 'amount over limit') END"

What's available inside a hook

Hooks vs. flows

Reach for a hook when the trigger is an ordinary CRUD change and the work is a side effect. Reach for a flow when you need a custom URL, a request/response shape of your own, or multi-step orchestration. They compose: a flow can write a row whose on_insert hook then sends the notification.

Related: Flows for custom endpoints, Workflows for state transitions, and Real-time to push changes to clients.