Real-time events your users never miss
Self-host a WebSocket event layer that authorizes every frame, replays missed events on reconnect, and scales across instances. Turn on chat and presence only where you need them.
Compose what you need
Run only the surface area your product uses
Pick from four Docker images. Transport is always in. Add chat, add presence, add both, or keep it pure for service-to-service events — same wire protocol, same SDKs.
Transport
Ship events now, catch up missed ones on reconnect. Publish, subscribe, ephemeral triggers, delivery acks, stream and member CRUD, multi-tenant auth — the core you get in every image.
ghcr.io/skeptik-io/herald-transportChat engine
Drop in the chat semantics you'd otherwise hand-roll — edits, deletes, reactions, read cursors, typing indicators, and server-side block filtering that stops fanout before it leaves the box.
ghcr.io/skeptik-io/herald-chatPresence engine
Real presence, not just a green dot. Manual away / dnd / appear-offline with per-override expiry, a tenant-wide broadcast stream, watchlist awareness, batch queries, and overrides that survive restarts.
ghcr.io/skeptik-io/herald-presenceSocial (default)
Everything wired up — full chat and rich presence in one image. Reach for this when you're building messaging, team workspaces, or creator platforms.
ghcr.io/skeptik-io/heraldDelivery semantics
Go fast by default, go durable when it matters
Every subscriber gets sub-millisecond fanout out of the box. Flip on ack mode for the streams that can't afford a dropped event and Herald redelivers until the client confirms — no client changes required elsewhere.
Best-effort real-time
Reach every connected subscriber in under a millisecond. Reconnect catch-up paginates through the WAL retention window, so a user who drops wifi for 20 seconds comes back caught up — not refreshed.
- ~8,000 msg/s, p50 0.10ms end-to-end
- Strict per-stream FIFO via atomic seq
- Paginated catch-up across reconnects
At-least-once (opt-in)
Set ackMode: "required" and Herald tracks acks per subscriber by seq. Unacked events redeliver on reconnect until the client confirms. Dedupe by seq on your side.
- Per-subscriber high-water-mark tracking
- Redelivery queue survives restarts
- Fully backwards compatible with no-ack clients
Production-grade
Answer the security review without a roadmap
Clustered fanout, end-to-end encryption, observability, audit trails, and GDPR deletion — everything buyers ask about, shipped in the binary. No plugins, no enterprise tier.
Scale out without sharding users
Run as many Herald instances as you need against a shared store and pub/sub backplane. Any subscriber receives events published on any node.
Encrypted at rest, out of the box
The ShroudB WAL encrypts every record with your master key. Skip the separate disk-encryption setup and the DB-level key management review.
E2EE your server can't read
TypeScript, Go, Python, and Ruby clients ship interoperable x25519 + AES-256-GCM with HMAC blind tokens for searchable encryption. Ciphertext in, ciphertext out.
Trace every event end-to-end
Per-stage latency histograms at /metrics and W3C traceparent propagation across HTTP and WebSocket frames via the otel feature — plug straight into your existing stack.
Answer auditors with a query
Chronicle v1.5 runs in-process with per-tenant hash chains, diff tracking, and a filterable query API. When compliance asks, you have receipts.
GDPR delete in one call
Admin endpoints purge a full tenant or a single user across streams, reactions, cursors, presence, and blocks — no manual cleanup across tables.
SDK coverage
Write in your language, stay on one protocol
Browser clients for real-time, admin SDKs for every backend language. The admin SDKs generate from OpenAPI and run against shared contract tests — so your Go service and your TypeScript service never disagree.
Browser / WebSocket
Run in the browser with zero external deps
- @skeptik-io/herald-sdkConnect, reconnect, dedupe, and encrypt — the browser client handles it for you
- @skeptik-io/herald-chat-sdkWire up edits, deletes, cursors, typing, and reactions without writing frame handlers
- @skeptik-io/herald-presence-sdkSet presence and clear overrides with one call from the browser
- @skeptik-io/herald-chatOwn your UI, borrow the state machine — messages, members, presence, typing, cursors
- @skeptik-io/herald-chat-reactShip faster in React with hooks and headless components
Server-side admin HTTP
Generated from OpenAPI, contract-tested across languages
- @skeptik-io/herald-adminTypeScript
- herald-admin-goGo
- herald-adminPython
- herald-adminRuby
- herald-admin-phpPHP
- Herald.AdminC#
Use cases
Built for the products you're already shipping
Chat and messaging
Ship a full messaging product without writing your own sync layer — typing, reactions, read receipts, edits, deletes, blocks, presence with overrides.
Collaboration tools
Broadcast cursors and selections at real-time speed with typing, presence, and ephemeral triggers you don't have to persist.
Creator and fan platforms
Give creators the presence controls they actually want — away, dnd, appear-offline — plus watchlist notifications scoped per tenant.
IoT and activity feeds
Get strict per-stream ordering, at-least-once delivery, and webhook mirroring for pipelines that can't drop an event.
Live dashboards
Push updates to every viewer in real time with ephemeral triggers, fanout filtering, and an OpenTelemetry trace on every frame.
Multi-tenant SaaS
Onboard tenants without provisioning infrastructure — isolated storage, self-service token rotation, per-tenant retention, one key+secret each.
Keep your database canonical. Use Herald for the live stuff.
Think Pusher, Ably, or Centrifugo — not a message store. The internal WAL is a short-horizon catch-up buffer (default 7 days, pruned hourly) so reconnecting clients replay the deltas they missed without refreshing the page.
Inside the buffer window, Herald owns deltas. Across it, your app database owns state. A webhook mirrors every event — edits, deletes, reactions — into your DB as it happens, so the two stay aligned.
Rule of thumb: if you're deciding where something lives past a reconnect window, it lives in your DB. Herald is the expiring pipe that remembers just long enough to make reconnects seamless.
Self-host quickstart
One container. One port. One master key.
Pull an image, generate a key, run the container. Herald provisions a default tenant on first boot — save the printed credentials and you're live.
docker pull ghcr.io/skeptik-io/herald:latest docker run -d \ -p 6200:6200 \ -e SHROUDB_MASTER_KEY="$(openssl rand -hex 32)" \ -e HERALD_AUTH_PASSWORD="your-admin-password" \ -v herald-data:/data \ ghcr.io/skeptik-io/herald:latest
Pick your image
heralddefault — chat + presenceherald-transporttransport onlyherald-chattransport + chatherald-presencetransport + presence
Your first event on the wire in a minute
Pull the image, run the container, provision a stream. No account to create, no sales call, no credit card.