Good Webhooks

Introduction

Good Webhooks is a TypeScript library that adds outbound webhooks to your application, using your PostgreSQL database.

Good Webhooks lets your application send webhooks to your customers. You publish an event; it handles the rest: who should receive it, signing, retries, history, and replay. It runs inside your app and stores everything in your PostgreSQL database. There is no extra service to host.

  1. your appPublish

    publish() validates the payload and finds subscribed endpoints.

  2. PostgreSQLStore

    The event and one delivery per endpoint commit with your data.

  3. workerDeliver

    A worker signs each request, sends it, and retries failures.

  4. receiverVerify

    The receiver checks the signature and gets a typed event.

The life of one event

In code

app.ts
import { createWebhooks } from 'good-webhooks'
import { Pool } from 'pg'
import { z } from 'zod'

export const webhooks = createWebhooks({
  database: new Pool({ connectionString: process.env.DATABASE_URL }),
  encryptionKey: process.env.WEBHOOK_ENCRYPTION_KEY!,
  events: {
    'invoice.paid': z.object({ invoiceId: z.string(), amount: z.number().int() }),
  },
})

await webhooks.publish({
  type: 'invoice.paid',
  data: { invoiceId: 'inv_123', amount: 4200 }, // type-checked against the schema
})

What it handles for you

Most teams start with a fetch() in a request handler. Then a customer's server goes down and events are lost, a deploy sends duplicates, or a URL points at an internal service. Good Webhooks covers those cases:

Good Webhooks handlesYou decide
Endpoint storage, encrypted secrets, URL safety checksWho may manage which endpoints
Payload validation, idempotency, recipient selectionWhen to publish, and in which transaction
Signing, retries, attempt history, replayWhere the worker runs and how it's supervised
Migration SQL and schema checksWhen migrations run
Signature verification and typed parsing for receiversWhat the receiver does with the event

Nothing starts on its own: creating the client opens no connections, runs no migrations, and starts no workers.

Beta

The public API is frozen except for correctness and security fixes. Pin the exact version and read the stability policy and the release notes before upgrading.

Where to go next

On this page