Upgrade guide
#1.0 (from 0.x)
The 1.0 release is the first version aligned with the IETF specification's typed-matcher model. It is a breaking change for both subscribers and JWT issuers. Publishers are unaffected.
If you only run the hub and don't author subscribers or mint JWTs yourself, the upgrade is a config change. If you do, plan a synchronized cutover of the hub and the clients that talk to it.
#What changed at a glance
| Area | 0.x | 1.0 |
|---|---|---|
| Subscribe query parameter | topic=<pattern> (URI Template or string) | match=<exact>, matchURLPattern=<pattern>, matchRegexp=<pattern>, ... |
| Default templating language | URI Templates (RFC 6570) | URL Patterns (WHATWG) |
mercure.subscribe / mercure.publish claim | Array of strings | Array of objects {match, matchType, payload} |
| Wildcard | "*" (string) | {"match": "*"} (object) |
| Subscription event topic | /.well-known/mercure/subscriptions/{topic}/{subscriber} | /.well-known/mercure/subscriptions/{matchType}/{match}/{subscriber} |
| Subscription JSON-LD | topic | match + matchType |
| Backward-compat mode | protocol_version_compatibility 7 | Removed |
#Migrate your subscribers
The single change is the query parameter name.
Before (0.x):
// Migrate your subscribers
const url = new URL("https://hub.example.com/.well-known/mercure");
url.searchParams.append("topic", "https://example.com/books/1");
url.searchParams.append("topic", "https://example.com/books/{id}");
new EventSource(url);
After (1.0):
// Migrate your subscribers
const url = new URL("https://hub.example.com/.well-known/mercure");
url.searchParams.append("match", "https://example.com/books/1");
url.searchParams.append("matchURLPattern", "https://example.com/books/:id");
new EventSource(url);
Two things to notice:
- The exact-match parameter is now
match(alias:matchExact). The hub treats query parameter names case-insensitively for any name starting withmatch. - The templated parameter is
matchURLPattern, and the syntax is URL Patterns (/:id, not/{id}).
If your existing patterns are URI Templates and you'd rather not rewrite them, the hub still supports them via matchURITemplate. New code should use URL Patterns, they're better-defined for URLs and the only matcher type natively supported by browsers.
#Migrate your JWTs
The mercure.publish and mercure.subscribe claims must now contain objects, not bare strings. The hub rejects bare strings with a 401 Unauthorized and refuses to mint a session.
Before (0.x):
// Migrate your JWTs
{
"mercure": {
"publish": ["*"],
"subscribe": [
"https://example.com/users/42",
"https://example.com/books/{id}",
],
},
}
After (1.0):
// Migrate your JWTs
{
"mercure": {
"publish": [{ "match": "*" }],
"subscribe": [
{ "match": "https://example.com/users/42" },
{ "match": "https://example.com/books/:id", "matchType": "URLPattern" },
],
},
}
Rules:
matchTypedefaults to"Exact"if omitted, so any plain URL or string can stay as{ "match": "<value>" }.- The reserved value
{ "match": "*" }matches every topic. It's the equivalent of the old"*"string. matchTypeis case-insensitive:"URLPattern","urlpattern", and"UrlPattern"are equivalent.- The
payloadfield is per-claim-entry, with explicit fallback rules when several entries match.
#Migrate the subscription API and events
The route pattern and the JSON-LD shape changed.
| Before | After |
|---|---|
/.well-known/mercure/subscriptions/<topic>/<subscriber> | /.well-known/mercure/subscriptions/<matchType>/<match>/<subscriber> |
"topic": "https://..." in the JSON-LD | "match": "https://..." and "matchType": "URLPattern" |
<matchType>, <match>, and <subscriber> must be percent-encoded. See Active subscriptions for the new layout.
#Compatibility mode is gone
In 0.14, the protocol_version_compatibility 7 directive let the hub speak the old protocol while you migrated. 1.0 removes it. The reasoning is that the JWT claim form changed from string to object, and silently re-interpreting old tokens under the new rules would change their meaning, that's a security risk, not a convenience. Mint new tokens.
#Mercure 1.0 find-and-replace checklist
Search your codebase for these patterns:
?topic=and&topic=in subscriber URLs ->match=(ormatchURLPattern=if templated)searchParams.append("topic"/appendParam("topic"->"match"- URI Template syntax in subscribe URLs (
{id},{+host}) -> URL Pattern syntax (:id,:host) "publish": ["*"]in JWT issuer code ->"publish": [{"match": "*"}]"subscribe": ["..."]in JWT issuer code ->"subscribe": [{"match": "..."}]- Hardcoded
subscriptions/{topic}/{subscriber}paths -> add the{matchType}segment
Once your services emit and parse the new shapes, switch the hub to 1.0.
#Mercure hub configuration changes in 1.0
Two directives that no longer exist:
protocol_version_compatibility: removed.transport_url: removed (deprecated since 0.17). Usetransport <name> { ... }.
The legacy non-Caddy server (deprecated since 0.11) is also removed. If you're still on it, see Installation for the current builds.
#Historical changes (0.x)
The entries below describe earlier upgrades. They are kept for users migrating across multiple major versions.
#Mercure 0.21 upgrade notes
When Mercure is compiled manually or used as a Go library, deprecated features are no longer included by default.
To re-enable deprecated transports, pass the deprecated_transports build tag when compiling Mercure:
# Mercure 0.21 Upgrade Notes
go build -tags deprecated_transport
To re-enable the legacy HTTP server, pass the deprecated_server build tag.
Official binaries and Docker images still include deprecated features.
#Mercure 0.17 upgrade notes
The MERCURE_TRANSPORT_URL environment variable and the transport_url directive were deprecated in favor of the transport directive.
Before:
# Mercure 0.17 Upgrade Notes
transport_url bolt://mercure.db?cleanup_frequency=0.2
After:
# Mercure 0.17 Upgrade Notes
transport bolt {
path mercure.db
cleanup_frequency 0.2
}
To configure the transport via an environment variable, append the directive to MERCURE_EXTRA_DIRECTIVES. Avoid putting credentials there; use {env.MY_VAR} placeholders in a custom Caddyfile instead.
#Mercure 0.16.2 upgrade notes
Caddyfile.dev was renamed to dev.Caddyfile to match Caddy best practices.
#Mercure 0.14.4 upgrade notes
This release moved to Caddy 2.6, which removed single-hyphen long-form flags. Use --config instead of -config.
#Mercure 0.14.3 upgrade notes
The Prometheus metric mercure_subscribers was renamed mercure_subscribers_connected for better interoperability with Datadog and others.
#Mercure 0.14.1 upgrade notes
The default development key changed from !ChangeMe! to !ChangeThisMercureHubJWTSecretKey! to satisfy the spec's 256-bit minimum.
#Mercure 0.14 upgrade notes
The Last-Event-ID query parameter was renamed lastEventID. Update your clients.
Publishing public updates in topics not listed in mercure.publish was removed; use ["*"] to keep the old behavior.
A protocol_version_compatibility 7 directive was added to ease the transition. It has since been removed in 1.0.
#Mercure 0.13 upgrade notes
The DEBUG environment variable was removed. Set GLOBAL_OPTIONS=debug instead.
#Mercure 0.11 upgrade notes
The hub became a Caddy module. Standalone binaries are now custom Caddy builds. The legacy server stayed available with a legacy build prefix until 1.0.
Before switching, migrate your configuration.
#Mercure 0.10 upgrade notes
The protocol changed substantially. Highlights:
- Targets are gone, replaced by topic selectors. Mark updates
privateand check themercure.publish/mercure.subscribeclaims. - Subscription JSON-LD:
"@type": "https://mercure.rocks/Subscription"->"type": "Subscription". dispatch_subscriptions->subscriptions.subscriptions_include_ipremoved; usemercure.payload.- IDs are now URNs (
urn:uuid:...). *as a topic became reserved.
#Mercure 0.8 upgrade notes
- Hub URL changed from
/hubto/.well-known/mercure. HISTORY_CLEANUP_FREQUENCY,HISTORY_SIZE,DB_PATHcollapsed intoTRANSPORT_URL.ACME_HOSTS,CORS_ALLOWED_ORIGINS,PUBLISH_ALLOWED_ORIGINSswitched to space-separated values.- The Go library's public API was rewritten.