Good Webhooks

Production checklist

Everything to settle before real customers receive webhooks, with a link to the details for each item.

Work through this list once before launch. Each item links to the page that explains it.

Keys and secrets

  • The storage encryption key is generated once, kept in a secret manager, and loaded by every app and worker process. Never generate it at startup. Manage endpoints
  • Signing secrets are shown to the customer once, over a secure channel, and never logged. Security model
  • You know how to rotate both a signing secret and the storage key. Key rotation

Database

  • Migrations run through your migration tool, not at app startup. Migrations
  • Every process calls check() at startup and fails fast on SCHEMA_MISMATCH.
  • Pool sizes and statement timeouts are budgeted across app, worker, and cleanup processes. Run workers

Publishing

  • Events are published inside the transaction that changes your data, where the tables share a database. Publish events
  • Every publish() that can repeat has an idempotencyKey derived from the business fact.
  • Your app authorizes the caller before choosing a scope. Scopes don't check permissions. Scopes
  • allowLocalhost is off.

Worker

  • At least one worker runs as its own supervised process, restarted with backoff on failure. Run workers
  • SIGTERM aborts the worker's signal, and the supervisor's kill deadline is longer than shutdownGraceMs.
  • Worker failures are logged and alerted on: either run() rejects and the process exits, or your onError logs and you watch that deliveries keep moving. Handle failures
  • You have read what a crash, a dropped connection, and a hard kill do to in-flight work. Failure behavior
  • You have compared your receiver latency and volume against the measured profile and sized concurrency and maxInFlight accordingly. Performance

History

  • A cleanup job calls prune() on a schedule. Workers never delete history. Retention
  • Delivery history is treated as customer data: it holds payloads and response bodies.
  • Support staff know how to inspect deliveries and replay one. Retries and replay

Receivers

  • Receivers verify the raw body and record event.id with their change, so retries and replays are harmless. Receive webhooks
  • Event names stay backward compatible. Breaking payload changes get a new name, such as invoice.paid.v2.

Upgrades

  • The package version is pinned exactly, and you read the release notes before upgrading. Compatibility

On this page