Mercure 1.0 alpha is available. Check out the new docs
Sponsored by Les-Tilleuls.coop
DocumentationSpecificationCloudDemos
Contribute!

High availability

The open-source Mercure hub is a serious piece of software. A single instance comfortably handles tens of thousands of concurrent connections on modest hardware (benchmark: 40k concurrent on a t3.micro). For most production workloads, one node is enough.

What one node can't give you is redundancy. If the box goes down, every subscriber reconnects to nothing. If the disk fails, the BoltDB history is gone. If you want to survive that, you need more than one node. And more than one node needs a transport that synchronizes between them.

This page covers your options.

What the open-source build gives you

CapabilityOpen-source
Concurrent connectionsUnlimited (hardware-bound)
Publish rateUnlimited
History bufferUnlimited (disk-bound)
Number of nodes1
TransportsBoltDB, local
TLS, HTTP/2, HTTP/3Yes
AuthorizationFull JWT support
Metrics, profilingFull Prometheus + pprof
Subscription eventsYes

The "1 node" line is the only ceiling. Everything else is unbounded by the license; only by what your hardware and network can deliver.

When one node isn't enough

Three reasons people graduate to multi-node:

  1. Redundancy. A single replica is a single point of failure. For real-time SLOs (sub-second delivery, no perceptible reconnect), you need more than one replica.

  2. Throughput beyond a single host. A box can usually push as much as its NIC allows, but multi-host gives you horizontal scale for fan-out: 1M-subscriber broadcasts split across nodes.

  3. Geo-distribution. Multi-region deployments need a transport that crosses regions cheaply.

Connection counts alone rarely justify multi-node. A single hub at 100k concurrent connections is normal.

The two paths beyond single-node

Mercure Cloud (managed)

A hub provisioned on the Mercure.rocks Cloud. High-availability infrastructure, TLS, custom domains, SRE on call. You don't run anything.

Tier€/monthConnectionsHistory
Free025None
Hobby351,000100 messages
Pro1205,000500 messages
Business45020,0005,000 messages

The buffer caps exist because managed hubs need predictable storage. If you need more history per topic, run Self-Hosted instead.

The protocol is identical. Migrate later by changing one URL.

Self-hosted Mercure (multi-node, on your infrastructure)

A licensed build of the same hub with multi-node transports added. You run it on your servers (bare metal, your own Kubernetes, your own clouds). Data never leaves your infrastructure. Useful for GDPR data residency, HIPAA, and internal compliance.

Tier€/yearConnectionsNodesHistorySupport
Open Source0Unlimited1UnlimitedCommunity
Startup1,5001,0002UnlimitedEmail
Business5,00010,0003UnlimitedPriority next-day
Corporate12,000UnlimitedUnlimitedUnlimitedPriority + SLA
EliteCustomUnlimitedUnlimitedUnlimited24/7 + SLA

A separate Managed On-Premise add-on (€5,000/year) covers remote setup, monitoring, and managed updates if you want the binaries on your infra without running them yourself.

To purchase, email contact@mercure.rocks.

Self-hosted transports

Redis / Valkey

The default for low-latency multi-node. Good fit when the hub is one of several services and the data is volatile.

# Redis / Valkey
mercure {
  transport redis {
    url    rediss://default:p@ssw0rd@redis.example.com:6379
    stream mercure
  }
  # ...
}
FeatureSupported
History
Subscription API
Custom event ID

Options:

OptionDescription
urlRedis connection URI (spec).
streamRedis stream name. Default: mercure.
max_lengthApproximate maximum stream size. 0 for unlimited.
gobUse Go gob instead of JSON. Faster, but can't be read by other clients.
addressesMultiple Redis nodes (cluster).
username, password, tlsAuthentication and transport security.

Reuse an existing Caddy storage Redis (when you also use caddy-storage-redis) by passing address caddy-storage-redis.alt.

PostgreSQL

The Postgres transport uses LISTEN/NOTIFY for pub/sub and SQL tables for history. Right when you want events queryable from the rest of your data.

# PostgreSQL
mercure {
  transport postgres {
    url postgres://user:password@db.example.com/mercure
  }
}
FeatureSupported
History
Subscription API❌ (planned)
Custom event ID

The Postgres transport doubles as an event store. You can join Mercure events with your application data in a single query, which is useful for audit, analytics, and replays.

Apache Kafka

Use Kafka when it's already in your stack and you want Mercure to ride on it. Otherwise, prefer Redis or Postgres.

# Apache Kafka
mercure {
  transport kafka {
    addresses host1:9092 host2:9092
    topic mercure
    consumer_group hub-pod-3
  }
}
OptionDescription
addressesBroker addresses.
topicKafka topic. All hub instances must share the same topic.
consumer_groupConsumer group. Must be unique per hub instance.
user, password, tlsSASL credentials.
FeatureSupported
History
Subscription API
Custom event ID

Apache Pulsar

# Apache Pulsar
mercure {
  transport pulsar {
    url pulsar://pulsar.example.com:6650
    topic mercure
    subscription_name hub-pod-3
  }
}
FeatureSupported
History
Subscription API
Custom event ID❌ (planned)

Picking a Mercure self-hosted transport

NeedTransport
Lowest latency, simplest setupRedis / Valkey
Queryable history alongside app dataPostgreSQL
Already running KafkaKafka
Already running PulsarPulsar
Single node, no extra infraBoltDB (open-source)

When in doubt, Redis. It's the recommended default for Self-Hosted.

Custom Mercure transports

The transport interface is small and public. If none of the above fits, write your own. See transport.go and build a custom hub with xcaddy.

License keys

Self-Hosted is gated by a license key passed via MERCURE_LICENSE. The check runs in-process; the hub doesn't call back to a license server.

# License keys
MERCURE_LICENSE=<key> \
MERCURE_PUBLISHER_JWT_KEY=... \
MERCURE_SUBSCRIBER_JWT_KEY=... \
./mercure run

The license enforces node count and connection caps. Going over the cap doesn't crash the hub; it returns 429 Too Many Requests to publishers and refuses new subscribers.

Mercure migration paths

FromToWhat changes
Open-source single nodeCloudChange the hub URL on clients. JWT keys move to the dashboard.
Open-source single nodeSelf-HostedSame binary structure, with a license and a multi-node transport. Subscribe and publish APIs are byte-for-byte the same.
CloudSelf-HostedMigrate the hub URL and the keys. Keep the same JWTs.

There is no protocol fork: every tier speaks the same Mercure protocol. Code written against the open-source hub runs on Cloud and Self-Hosted unchanged.

Mercure vs. Pusher and ably: pricing comparison

For people coming from SaaS-only real-time platforms, here's the rough picture:

FeatureMercure Pro (€120)Pusher Business ($499)Ably Pro ($399+)
Concurrent connections5,0002,0005,000
History buffer500 messagesLimited2 minutes default
MessagesUnlimitedDaily capUsage-based billing
Self-hostable?YesNoNo

Mercure is the only one of these you can run on your own infrastructure if you need to. That's by design.

Mercure support channels

Next steps for Mercure high availability