baguette

Automations

Automations are an optional, event-driven layer built on Postgres LISTEN/NOTIFY. Instead of running on a clock like cron, an automation reacts to something happening in your database. Drop a file in automations/, and it wires itself up.

// automations/onPaymentPaid.ts — two named exports: details + automation.
// The trigger name is a Postgres channel: `<table>_insert | _update | _delete`.
export const details = {
  name: "onPaymentPaid",
  trigger: { name: "payment_insert" }, // fires on a new row in the Payment table
};

export const automation = async (payload: string) => {
  const payment = JSON.parse(payload); // the changed row, as JSON
  await grantAccess(payment.customerId);
  return { logs: [], status: "SUCCESS" as const };
};

How it works

  • File-based — one automation per file in automations/, mounted by convention.
  • LISTEN/NOTIFY — automations subscribe to Postgres notification channels. The framework can install the trigger DDL so a row change emits an event.
  • Double opt-in — this layer starts only when the automations/ directory exists and AUTOMATIONS=true. It stays dormant otherwise, so a plain HTTP deploy never opens a listener.
  • Raw SQL only — LISTEN/NOTIFY and trigger DDL use raw SQL; no ORM is imported.

Scaffold one

baguette new automation onPaymentPaid

This creates automations/onPaymentPaid.ts ready to fill in. See the CLI reference.

  • serve — gates automations behind AUTOMATIONS=true.
  • Cron — for time-based rather than event-based jobs.