Encrypted Group Chat on Nostr: Marmot, Concord, and Cordn Compared
Three protocols, three philosophies. Marmot brings MLS ratcheting to small high-stakes groups with no privileged server, Concord trades ratchets for Discord-style community scale, and Cordn runs MLS through a lightweight, self-hostable coordinator per group. Here is how they differ and when each one wins.
Pairwise encryption is a solved problem. Group chat is not. The moment a third person joins the room, questions appear that two-key crypto never had to answer. Who holds the group key? What happens to old messages when someone leaves? Who decides who belongs, and who verifies that decision? On a centralised platform, a server settles all of this by fiat. On nostr there is no server to settle anything, which is exactly why the interesting work is happening there.
Three protocols are currently answering these questions in public: Marmot, Concord, and Cordn. All three are end-to-end encrypted group messaging built on nostr. Past that shared opening, they diverge sharply: on the crypto layer, on the trust model, and on the shape of the group they assume you actually want. Star counts below are a snapshot at the time of writing.
The short version
| Marmot | Concord | Cordn | |
|---|---|---|---|
| Crypto layer | MLS (RFC 9420) | Shared key + NIP-59 giftwrap | MLS (RFC 9420) via coordinator |
| Forward secrecy | Yes | No | Yes |
| Post-compromise security | Yes | No | Yes |
| Coordinator needed | No | No | Yes, one per group |
| Trust model | No privileged server, relay-redundant | Signed roster + key possession | Coordinator per group (blind to content, identities, IPs) |
| Target size | Small, high-stakes, scaling up | Large, public | Same as MLS (coordinator-assisted) |
| Group features | Basic MLS groups | Full Discord-like set | MLS groups via coordinator |
| Spec maturity | Evolving (v2 in progress, breaking changes) | Evolving, 8 CORD docs | 3 spec docs + reference code |
| Implementations | MDK flagship (Rust, actively released); others catching up | 5 nostr clients (Armada, Vector, Accordion, Amethyst, Grimoire) | CLI, TS + Rust + KMP + browser + Android coordinators, cordn.net web + Android apps, cahmls |
| Membership change cost | O(log n) | O(n), key rotation to all members | O(log n) |
| Post-removal secrecy | Automatic, next epoch | Manual rekey (CORD-06) | Automatic, next epoch |
Marmot: MLS discipline for small, serious groups

Marmot (138 stars, MIT) is the closest thing nostr has to Signal-grade group crypto. It uses MLS, the IETF's Messaging Layer Security standard (RFC 9420), as its continuous group key agreement layer. Nostr keys provide identity, nostr event-shaped app payloads ride inside MLS envelopes, and nostr relays carry the bytes. Those three invariants (identity, key agreement, transport) are the protocol's spine. The spec is well structured and the older MIP-era documents are explicitly deprecated. A breaking v2 is in progress.
What MLS buys you is the good stuff. Forward secrecy, so past messages stay safe after a key compromise. Post-compromise security, so future messages heal after one. The price is lockstep: MLS advances through ordered commits, per-device key packages, and O(log n) cost per membership change. Every join, leave, or device addition ratchets the whole tree forward.
The guarantee is worth stating precisely: as long as every member receives every commit event, the group stays in consensus on MLS state. How the bytes travel is deliberately secondary, because no server is privileged anywhere in the design. Nostr relays are the first transport binding rather than the protocol's identity, and the MDK has already spiked a FIPS transport for the future.
The spec culture is unusually disciplined. It is organised by protocol surface: foundation, protocol-core, app-components, transports, and features, each with its own README, plus canonical-encoding, principles, and implementation-model documents, and a migration map from the deprecated MIPs. Normative language is used correctly. Transports MUST support redundant delivery, so no group ever depends on a single relay. The protocol SHOULD avoid new metadata leaks, alongside the honest admission that perfect metadata privacy is impossible in decentralised messaging.
The centre of gravity is the MDK, the Marmot Development Kit: a Rust workspace holding the OpenMLS-backed CGKA engine, SQLCipher-encrypted account and device storage, nostr transport adapters, and UniFFI bindings (MarmotKit) that app runtimes consume, plus a C ABI, a CLI, daemon and TUI, and Tamarin formal models that map the proofs back to tests. It releases on separate tracks (workspace, MarmotKit, Marmot C, and the wn-agent connector) and is the flagship library for the upcoming Marmot v2. The v2 work in progress is the kind that matters in production: two-phase group hydration, so cold-start readiness stops scaling with how many groups you have stored, and background hydration that queues sends in arrival order while catch-up completes. Around the MDK sit marmots-web-chat as the reference web client, plus implementations in TypeScript (marmot-ts), C# (marmot-cs), Dart and Flutter (marmot_dart), Rust (cove), and on the CLI (burrow), though at the time of writing several of these have not yet caught up to the current spec. The dr.marmot diagnostic tool rounds out the set.
On scale, groups of 64 members are working well today. The current ceiling is a set of arbitrary data limits rather than anything fundamental in MLS, and lifting them is expected to open larger groups, though sizes beyond that have not been tested. Scaling without a privileged server is the harder road: a coordinator can traverse the group graph in one place, while Marmot has to converge the same state through redundant relay fan-out. It is the road the project has chosen, and reliability improvements are landing in near-weekly MDK releases.
Target: small, high-stakes groups where forward secrecy matters and every membership change is a ratchet, not a chore.
The trade: the strongest crypto guarantees of the three, the most mature spec, and a flagship Rust implementation, in exchange for the decentralised road, where both convergence and metadata privacy are earned rather than granted by an operator.
Concord: Discord-style communities without the platform

Concord (58 stars, evolving specification) targets the opposite end of the room: large, public, high-churn communities. Channels, roles, owners, admins, kicks, bans, invites, voice and video, disappearing messages. The full platform feature set, but decentralised, end-to-end encrypted, and with no company in the middle.
Concretely: not MLS. The base primitive, CORD-01 "private streams" (spec), is a shared symmetric key distributed through NIP-59 giftwrap. Anyone holding the key can read the stream; relays see only ciphertext addressed to rotating labels. Membership is key possession. There is no ratcheting, no forward secrecy, and no post-compromise security. Removing someone means rotating the key, which is what CORD-06 rekeys and refoundings are for.
The trust model is the clever part. Concord splits the three jobs a central server normally monopolises:
- Storage and delivery go to dumb relays, which only ever see encrypted blobs.
- "Who is a member?" is answered by key possession. If you can decrypt the room, you are in it. There is no list to enforce.
- "Who is in charge?" is answered by a signed roster rooted in the owner's identity. Authority is a signature, not a switch, and every client re-verifies the chain independently.
The community_id is self-certifying and the control_root is a staff-held write key. A forged ban fails verification because it does not trace back to the owner.
The spec itself is a series of eight CORD documents, NIP-style, each a small self-contained piece:
| CORD | Title | What it does |
|---|---|---|
| 01 | Private Streams | Base shared-key stream over NIP-59 giftwrap |
| 02 | Communities | Membership and authority model, epochs |
| 03 | Channels | Public and private rooms |
| 04 | Roles | Granular, ranked, owner-rooted permissions |
| 05 | Invites | Shareable links, revocable, direct giftwrap invites |
| 06 | Rekeys & Refoundings | Post-removal secrecy via key rotation |
| 07 | Audio/Video | Blind token broker, SFU forwarding only ciphertext |
| 08 | Disappearing Messages | NIP-40 expiry, staff-set timer |
The README positions Concord against its neighbours precisely: NIP-17 private DMs cannot do communities and are DoS-vulnerable; NIP-29 relay-based groups require self-hosting an entire server and are not end-to-end encrypted; Marmot's MLS lockstep is heavy for large casual rooms; Iris Chat is pairwise ratchets, not communities.
Target: the Discord replacement. Large, public, asynchronous communities with real moderation needs.
The trade: the best community-management feature set of the three, no coordinator required, and asynchronous operation with no ordering requirement, in exchange for the crypto guarantees spelled out above: a single key compromise exposes the room until a rekey, and every removal costs O(n) key rotation to all remaining members. The spec is young but the ecosystem is growing: established nostr clients including Armada, Vector, Accordion, Amethyst, and Grimoire already support Concord communities.
Cordn: MLS with a coordinator per group

Cordn (10 stars, active development) takes MLS in a third direction: the same crypto family as Marmot, a different delivery architecture. Built on the ts-mls TypeScript implementation and exposed as a ContextVM server, it is a "minimal MLS delivery service coordinator" implementing the Delivery Service role from RFC 9420. Where Marmot refuses to privilege any server, Cordn embraces the coordinator role that MLS delivery assumes.
MLS assumes someone operates a delivery service: a place that stores per-device KeyPackages, routes Welcome messages to new members, and delivers group commits in order. Cordn's answer is to be that service, openly. Clients publish KeyPackages to it; group messages flow through with per-group monotonic cursors; clients follow a fetch-then-subscribe pattern for bounded catch-up and then live delivery, with multi-group variants for clients tracking many rooms. Clients communicate with the coordinator over ContextVM, while the coordinator itself speaks nostr, using CEP-22 oversized transfer and CEP-41 open streams over the ContextVM and Primal relays by default.
Membership is settled exactly as in Marmot: the MLS member list is the authority. You are in the group if you are in the tree, with the same forward secrecy and post-compromise security that implies.
The operational details are sensible. Token-bucket rate limiting is keyed by client pubkey, with storage quotas per identity, both tunable through environment variables. Deployment is a Docker image on GHCR with SQLite or in-memory storage, and there is an npm-published CLI, @cordn/cli. The implementation surface is broader than it looks: coordinators exist in TypeScript, Rust, Kotlin Multiplatform (KMP), and a browser-based variant that runs from a single HTML file. There is an Android coordinator app, the cordn.net web app and its Android counterpart, and cahmls, a browser-based coordinator plus alternative client. The spec is thin so far: three documents covering the coordinator and identity model, a group metadata extension, and a nostr-shaped app-message envelope.
Target: MLS-grade group messaging for teams happy to run (or share) a small coordinator per group.
The benefit: easier scaling and better metadata privacy. The coordinator handles delivery in one place, and nothing it carries ever appears as a protocol-specific event on a public relay. Relays see only generic encrypted ContextVM traffic, so unlike Marmot or Concord, there is nothing on a relay to fingerprint, cluster, or archive.
The trade: a coordinator can traverse the group graph in one place, so Cordn scales more easily than decentralised consensus, and whoever runs it can tighten public metadata handling. To be clear about what this is not: it is not a centralised platform. Coordinators are ordinary software, trivially self-hostable, small enough to run in a browser tab or on a phone, tolerant of intermittent availability, and no more than one per group, so different groups naturally run on different machines run by different people. The honest cost is per-group dependency: the group's delivery depends on its coordinator being reachable, even though the coordinator cannot read content.
What the coordinator can and cannot see
Being precise about the coordinator's vantage point matters, because "it runs a service" sounds scarier than it is. The coordinator is a delivery and signalling service, not a state authority. Everything that matters cryptographically (epoch keys, ratchets, the MLS member tree, KeyPackage secrets) lives client-side on each member's device.
What it can see:
- Client pubkeys (used for rate limiting and key package storage quotas)
- That a group is active (timing and volume patterns for the traffic it handles)
- Encrypted message blobs, Welcome messages, and join requests flowing through (all ciphertext, none of it readable)
- Per-group cursors and message ordering
- Any backlog of undelivered ciphertext queued on it at a given moment
What it cannot see:
- Message content (MLS end-to-end encryption protects it)
- Client IPs (clients never connect directly; they reach the coordinator through relays via ContextVM)
- Group membership secrets or historical messages already delivered to members
- Stable participant identities for routine traffic (ordinary message posting can use ephemeral transport keys, so the coordinator does not even learn who is talking for normal sends)
If a coordinator is compromised, subpoenaed, or turns hostile, what is at risk is only the backlog of undelivered ciphertext and the activity it can observe during the window it is your active coordinator. The group itself, its membership, its history on members' devices, and the ability to continue all survive. Migration to a different coordinator is designed in: per-group cursors preserve ordering across a move, so a group can jump from one coordinator to another because groups do not care which coordinator they live in.
The metadata story is where Cordn genuinely differs from the other two. Marmot and Concord both publish protocol-specific events to public relays: Marmot's kinds 443 and 445, Concord's 3300 range. An external observer can fingerprint the protocol, cluster traffic by group identifier, and read timing patterns. Cordn publishes none of its messaging artifacts to relays. KeyPackages, Welcomes, group messages, and join requests all live on the coordinator, reached through ContextVM, a general-purpose protocol for reaching services through relays without direct public exposure. The relay sees only generic, encrypted, ephemeral ContextVM traffic that blends with every other ContextVM usage. The party that can interpret the traffic (the coordinator) never sees an IP, because clients connect through relays. The party that can see an IP (the relay) cannot interpret the traffic. That severs the convergence of IP and protocol visibility that every relay-based scheme inherits. For a deeper analysis of these privacy models across all the nostr messaging protocols, see this long-form note.
Five takeaways
- Marmot and Cordn use MLS. Concord does not. Concord's shared-key model is simpler but cryptographically weaker, and for a large public community trading crypto guarantees for scalability and simplicity can be a rational trade.
- Marmot and Cordn are separate stacks, not layers of one system. Marmot cannot run over Cordn: both use MLS, but Marmot runs over decentralised relays while Cordn runs each group through its own small, self-hostable coordinator. Cordn trades that coordinator for scalability and better public metadata behaviour; Marmot keeps full decentralisation and is working out metadata privacy the harder way.
- Each targets a different room. Concord aims at large public communities, the Discord replacement. Marmot aims at small high-stakes groups, the Signal replacement, with headroom as data limits lift. Cordn is for groups happy to give the coordinator job to one small piece of software.
- If forward secrecy and post-compromise security are requirements, Marmot and Cordn are your options. Concord explicitly trades those guarantees for scale.
- Membership authority splits two ways. Marmot and Cordn settle it at the crypto layer: you are in the group if you are in the MLS tree. Concord's signed roster, owner-rooted and client-verified, is its own well-designed answer to community moderation without MLS.
Which one should you pick
Start with the group, not the protocol. A small team with secrets to keep wants ratchets, and Marmot is the most mature way to get them on nostr today. A public community of thousands with mods, roles, and a kick-and-ban workflow wants Concord, accepting that a compromised room key stays compromised until a rekey. And if you would rather run a coordinator than converge state across relays, Cordn is the MLS stack built around exactly that.
This is exactly the kind of question we like being handed before a line of code gets written. Protocol choices are cheaper to make correctly on day one, and we build nostr clients and relay infrastructure for a living. If you are weighing any of these for a product, talk to us.
