published 6/24/2026

Update 00

sup nerds. We now doing low-energy progress reports.

Here’s a summary of stuff that changed in the last 4? months. IDK my brain is so fried from talking to Claude all day.

Hop-based Routing

Now you can now arbitrarily connect moq-relay instances to each other to form a cluster. They’ll gossip available broadcasts to each other and proxy any subscriptions automatically via the shortest path.

For example, I can host a relay at https://denver.moq.dev and configure it with:

moq-relay --cluster-connect "https://chicago.moq.dev" --cluster-connect "https://seattle.moq.dev" ...

Imagine relays are also configured to connect to their nearest neighbors. A subscription from a user in Europe, subscribing to a broadcast in Denver, might travel:
Frankfurt -> London -> New York -> Chicago -> Denver

At each hop, we deduplicate subscriptions. Which means at most only one copy of a track will ever be transmitted between two relays.

bbb

SPOILER: an upcoming marketing image

For context, the previous architecture was a mesh. Every relay would connect to every other relay, which would have resulted in:
Frankfurt -> Denver (oof)

Oh yeah and Your local relay (snug behind a firewall) can proxy all broadcasts to/from a public CDN:

moq-relay --cluster-connect "https://cdn.moq.dev" ...

It’ll work with any other MoQ CDN… once they implement enough of the moq-transport spec (Cloudflare pls). But you’ll need moq-lite-03+ to establish multiple connections, otherwise a cycle will ruin your day.

Standards

Speaking of standards, the IETF keeps marching forward, so I have to “support” every new draft version:

We don’t support every single feature because some of them are dumb and it takes forever to litigate every single addition/change in the IETF. I’m starting to publish extensions for stuff we add on top, but it’s such a drain on my time.

Instead the moq.dev libraries prefer to negotiate:

moq-lite-05 is coming SOON with more stuff.

Muxing

My philosophy is that we should not transmit arbitrary media formats over MoQ. It’s possible to transmit TS over MoQ verbatim, but then every player/subscriber needs to decode Transport Streams (gross).

Instead, moq-mux is our transmuxing layer. We can import/export other formats without re-encoding, preserving the intent but not the original structure.

Here’s the codecs we support:

And the containers we support:

Going back to Transport Streams (gross) as an example. When you import a TS stream with moq-mux, we’ll split A/V into MoQ tracks, but we’ll also preserve “unknown” tracks with a special “ts” section. If you export the same stream to TS with moq-mux, we’ll re-assemble the TS stream and reinsert the unknown tracks.

This is a REALLY BIG DEAL for broadcast TV. Your precious SCTE35 markers are preserved AND you’re not wasting 5% of your bandwidth on 188-byte packets.

ur welcome

CLI

Note that moq-mux is available as both a library and a CLI via moq-cli.

# Publish: pipe in a MPEG-TS file
ffmpeg -re -i input.ts -f mpegts - | \
    moq-cli publish --url https://cdn.moq.dev/anon --broadcast my-stream ts

# Subscribe: pull MPEG-TS back out and play it
moq-cli subscribe --url https://cdn.moq.dev/anon --broadcast my-stream --format ts | \
  ffplay -

You can download all of the moq binaries (moq-relay, moq-token, etc) from your favorite package manager:

For specific commands, see the CLI docs. Cool I guess?

JSON

JSON isn’t known for its efficiency.

moq-json (Rust) and @moq/json (Typescript) publish arbitrary JSON over MoQ tracks. The first frame in each group is a full snapshot, then subsequent frames are JSON Merge Patch deltas. We periodically make new groups so late joiners can catch up without having to download the entire stream.

We also stack moq-flate (Rust) and @moq/flate (Typescript) to add DEFLATE compression on top. Normally you would compress each frame individually, like a gzip file, but it turns out we can do significantly better by using Z_SYNC_FLUSH. Each subsequent frame within the same group can reuse the previous frames as a compression window, instead of starting from scratch.

Claude ran a benchmark over a synthetic stream of JSON sensor snapshots. The type of output you’d expect from a drone.

Bitrate savings for different configurations:

No DEFLATEDEFLATE per frameDEFLATE per group
No deltas0%39%89%
JSON Merge Patch58%72%91%

I was surprised to see how important Z_SYNC_FLUSH is given it’s not supported by the browser implementation and is bugged in the most popular Javascript implementation. At this point, the main benefit of JSON Merge Patch is to save some CPU cycles.

Backends

We’ve used Quinn for the longest time, but now you can use other QUIC backends! Why? IDK different features and performance.

QUIC Backends (both WebTransport + raw QUIC):

You can also use non-QUIC backends with Qmux! It emulates a QUIC connection, but over a reliable transport. We do suffer more from head-of-line blocking so it’s worse than QUIC, but sometimes it be like that.

Non-QUIC Backends (Qmux):

I’m using WebSockets as a TCP fallback (when QUIC is not available) and unix domain sockets to avoid paying the TLS/UDP overhead tax on localhost. It’s still Media over QUIC even if QUIC is not used…

UI Polish

Claude made the web UI look better. tfw an AI has better taste than me.

Clone the repo and run just dev to see:

bbb

he a sniffer

You can use the UI on your own site via the web components:

<script type="module">
    import "https://esm.sh/@moq/watch/element";
    import "https://esm.sh/@moq/publish/element";
</script>

<moq-watch-ui>
	<moq-watch url="https://cdn.moq.dev/demo" name="bbb.hang">
		<canvas style="max-width: 100%; height: auto; margin: 0 auto; border-radius: 1rem;"></canvas>
	</moq-watch>
</moq-watch-ui>

There’s also one for <moq-publish> which is equally slick.

Polyglot (Alpha)

We full monorepo now.

moq-ffi uses Uniffi to generate async bindings for various languages. It’s all the same Rust code under the hood, but IDK now you can use it on iOS/Android/whatever. MoQKit uses it.

neat

Supported:

I’m still working on more ergonomic bindings for each language, hence the (Alpha) tag.

Oh and don’t worry, we still have C support via libmoq. moq-ffi is for the async languages who don’t want to deal with callbacks and APIs designed for dinosaurs.

Production Stuff

I’m almost done spinning up a PAID MoQ CDN. It’s like a week or two away, GET HYPED.

As part of that, I actually have to make sure everything is production-ready, which means focusing on the boring stuff. Stuff like making static configurations… dynamic.

And finally my favorite one, but it deserves its own blog post later:

Conclusion

I hope you enjoyed this low-energy update. Super low.

Written by @kixelated. @kixelated