29k+ events · open source

Every notification,
accounted for.

Herald is an open-source notification system built on a transactional outbox. One commit writes the event, its timeline, and the outbox. Then every delivery is tracked to a terminal state. 29,989 events in, zero lost.

Free and open source. One command to run.

How it works

One promise,
three mechanisms.

Each mechanism exists for one reason: a notification must never silently disappear.

01 / Commit

Accept first.
Decide later.

The event, its timeline, and the intent to publish commit in a single Postgres statement. Your API returns 202 only after the work is durable.

  • One SQL statement, three writes
  • 202 after the commit, never before
  • The outbox is the recovery plan
See it run locally →
one transactionPostgres
notificationsevent, recipient, policyinsert
notification_eventsappend-only timelineinsert
outboxpublish intentinsert
02 / Receipts

Numbers,
not adjectives.

Don't take our word for it: every figure on this page comes from a run you can repeat with one command.

  • 29,989 events accepted in 10 minutes
  • 0 failed requests at 50/s
  • 4.10s from timeout to replay
See the receipts →
backlog after 10 minutes3 runs
1,200 600 0 50/s 60/s 70/s
03 / Trace

The failure has
a paper trail.

When a provider times out, you see the whole story (unknown, dead letter, replay, recovered) under one trace ID.

  • Policy hash and channels considered
  • Every attempt with error class and latency
  • Inbox state and outbox state in one place
Replay it yourself →
trace 6f3c21aa4.10s
acceptedcommit
fanout planned3 channels
push unknowndead letter
replay appliedsame ID
recovered1 item

Runs on the stack you already have.

NodePostgresKafkaRedisDockerMailpitGitHub
Receipts

Measured,
not promised.

One 10-minute run on a 4-core laptop, not a cloud benchmark. Every number is reproducible from the repository.

29,989

events accepted

0 failed

0

accepted events lost

SIGKILL tested

4.10s

timeout to replay

same ID

Also measured: 4.3M events/day · 71,052 deliveries · 11.6s p95 · 36s recovery after SIGKILL. Raw results ship with the repo.

Run it

Running beats
reading.

Three setups, same guarantee. Pick the smallest one that proves it to you.

Start here

One command.

The smallest setup that shows the outbox and the trace end to end.

make demo
  • Postgres, Redis, Kafka, Mailpit
  • API and one core worker
  • A seeded notification you can trace
Get the code
Go deeper

Break it yourself.

Kill processes, replay dead letters, and check that nothing goes missing.

pnpm herald doctor
  • Capacity model and 10-minute runs
  • Crash test with SIGKILL
  • Trace API and dead-letter replay
Get the code
Scope

Limits,
written down.

Herald is a local demo shaped like production, not production itself. What is missing is listed here, not hidden.

Read the capacity model →
One Postgres shard, one Kafka broker, one Redis

The demo keeps the dependency footprint small. It is not a claim about a multi-region deployment.

Push and SMS are deterministic mocks

Email goes to Mailpit. Push and SMS return scripted outcomes so the failure path is reproducible.

300M events/day is a design target, not a measurement

The measured ceiling is 4.3M events/day on the 4-core laptop used for the runs.

Local tables are not partitioned

Retention deletes in batches. Partitioning is the first change for a larger deployment.

Stop losing
notifications quietly.

Run the demo, trace one notification, and check the receipts yourself.

Free and open source. MIT licensed.