I blamed HTTP/2 multiplexing. Then I counted the connections.
Every request succeeded. The log stayed 33,000 entries behind. The mechanism I blamed was real, present, and not the problem.
A drop-in certstream server that aggregates newly issued SSL/TLS certificates from every Chrome- and Apple-trusted Certificate Transparency log and streams them over WebSocket and SSE. RFC 6962 and static-CT-API, in a single binary.
docker run -d -p 8080:8080 ghcr.io/reloading01/certstream-server-rust:latest
Built for security teams, researchers, and developers who need reliable Certificate Transparency monitoring.
WebSocket and Server-Sent Events. WebSocket for real-time clients, SSE for browsers and pipelines — same data, your choice of transport.
Both the classic get-entries protocol and the new checkpoint + tile static-ct-api logs are watched side by side in one process.
The same certificate shows up across many logs. A SHA-256 filter collapses duplicates so each client sees a clean, single stream.
Resume from the last processed position after a restart. No certificate loss during maintenance or upgrades.
Per-IP and total connection caps. Production-ready protection against abuse and runaway clients.
Bearer-token access control with constant-time comparison. Multiple tokens, configurable header name.
Configuration changes apply without a restart. A file watcher picks up edits for zero-downtime tuning.
Automatic retry with exponential backoff and per-log circuit breaking. Failing logs are isolated, not allowed to spam.
A Prometheus /metrics endpoint plus an optional REST API for server stats, log health, and certificate lookup.
The wire format is the one Calidog's certstream-server established and certstream-server-go kept, so existing clients work unchanged.
import certstream certstream.listen_for_events(callback, url='wss://your-host:8080/')
# same certificate_update messages, # same all_domains, same leaf_cert wscat -c wss://your-host:8080/
Message types, field names and the leaf_cert shape are unchanged, so parsers written
against either predecessor keep working. What you gain is coverage and cost: the tile-based
static-CT-API logs that now carry most issuance, cross-log deduplication so the same certificate
does not arrive three times, and the resource profile above. If you only want hostnames, the
/domains-only stream cuts about 4 KB per certificate down to roughly 200 bytes.
All 45 Chrome- and Apple-trusted logs, default configuration, one subscriber on the domains-only stream. Sampled every 30 seconds over two hours.
That is 36 million certificates a day on a fifth of one core. Each certificate is serialized once
and broadcast to every subscriber through an Arc<PreSerializedMessage> with
zero-copy text frames; when nobody is connected, serialization is skipped outright. Memory is
flat rather than merely bounded, and the reasoning behind that number is written up in
358 MB resident, 52 MB in use.
Every request succeeded. The log stayed 33,000 entries behind. The mechanism I blamed was real, present, and not the problem.
Three logs, zero errors, 279,000 entries behind. The fast way to read them was sitting right there, behind a missing file.
A service that looked like it was leaking. It wasn't, and the fix was five settings the allocator had been running without.
I build this in my free time. Just using it, starring the repo, or sharing it with someone who needs it already means a lot — that's the kind of thing that keeps me going.
If you'd like to go a step further, you can sponsor me on GitHub. No pressure though — every form of support is appreciated.