Products / SaaS / Backend Infrastructure

Live

HookQueue

HMAC webhooks → idempotent ingest → SKIP LOCKED worker

HMAC-verify inbound webhooks, store each event once on (provider, externalId), and process work in a Postgres FOR UPDATE SKIP LOCKED worker with pluggable handlers.

Value

Problem. Every SaaS eventually receives provider webhooks. Retries re-deliver the same event; naive handlers double-charge, double-email, or race across workers.

How it helps. HMAC-verify inbound webhooks, store each event once on (provider, externalId), and process work in a Postgres FOR UPDATE SKIP LOCKED worker with pluggable handlers.

Why buy. Own a readable Node/TS/Postgres webhook spine instead of bolting Redis queues or rewriting signature + dedupe glue again.

How it works

flowchart LR
  Provider[Webhook Provider] -->|POST /webhooks/:provider| API[Express API]
  API -->|HMAC verify| API
  API -->|unique provider+externalId| DB[(PostgreSQL)]
  Worker[Worker SKIP LOCKED] -->|claim pending| DB
  Worker -->|handler| Handler[Pluggable Handler]
  Handler -->|done / failed| DB

Mermaid flowchart (render in GitHub / VS Code / mermaid.live).

Use case

Stripe invoice.paid (or GitHub push) hits your API; HookQueue verifies the signature, stores the event once, and a worker marks it done after your handler runs — retries return duplicate without a second enqueue.

What you get

Project structure

hookqueue/
  src/
    app.ts, index.ts
    lib/          config, hmac, logger, prisma
    routes/       health, webhooks
    services/     ingest, handlers
    worker/       claim, process, index
  prisma/         schema + migrations
  tests/          hmac, ingest, claim, process, config
  scripts/        sign-webhook.mjs
  docker-compose.yml

Quick start

docker compose up -d
cp .env.example .env  # set WEBHOOK_SECRET
npm install && npm run prisma:generate && npm run prisma:migrate
npm run dev
npm run worker

Example

From src/lib/hmac.ts

import { createHmac, timingSafeEqual } from "node:crypto";

export function signPayload(rawBody: string | Buffer, secret: string): string {
  return createHmac("sha256", secret).update(rawBody).digest("hex");
}

// Header: X-HookQueue-Signature: sha256=<hex>
// Verify with timingSafeEqual against the raw request body.

Tested

22 Vitest tests across 5 files — HMAC sign/verify, Zod + idempotent ingest (P2002 → duplicate), claim exclusivity, process done/failed.

npm test

2026-09-20 — 22 passed; npm run build OK

Design decisions

Limitations

Who it’s for

Indie SaaS founders and backend engineers who need reliable Stripe/GitHub/custom webhook ingest on Node + Postgres.

Not for: Teams that need a hosted webhook SaaS, Redis-first queues with dashboards, or non-Postgres stacks.

What you own

Full MIT-licensed TypeScript source via Gumroad ZIP. Fork it, ship it commercially, keep the license notice. You are responsible for secrets, hardening, and production ops.

Related

TenantScope · CronLock · IdemKey · RateGuard

Demo

HookQueue demo
Live Postgres demo — HMAC reject (401) → valid accept (202) → duplicate ignored (200); row stored in webhook_events.
Buy HookQueue — $19 All products