A few properties set Matrix apart from the typical client-server chat you know:
m.room.message, m.room.member, m.reaction…) cover the everyday case; custom types let you build polls, maps, CRDTs, collaborative editors, game state, IoT telemetry — anything that wants a decentralized replicated log with auth.curl.Federation (Server-Server API, HTTPS+JSON) ┌─────────────────────────────────────┐ │ │ ┌───────────┐ │ ┌───────────┐ ┌──────────┐ │ ┌───────────┐ │ Element │──┼──▶ │ your. │ ◀───▶ │ matrix. │◀┼─── │ FluffyChat│ │ (web) │ │ │ meldry. │ │ org │ │ │ (mobile) │ │ │◀─┼─── │ com │ │ │ │─── │ │ └───────────┘ │ └───────────┘ └──────────┘ │ └───────────┘ │ ▲ ▲ │ │ │ │ │ │ ▼ ▼ │ │ ┌───────────┐ ┌──────────┐ │ │ │ bridges, │ │ appsvcs, │ │ │ │ appsvcs │ │ bots │ │ │ └───────────┘ └──────────┘ │ └─────────────────────────────────────┘ Client-Server API Server-Server API (what Element talks) (what homeservers talk to each other)
your-name.meldry.com can chat with a user on matrix.org without a middleman.You pick the client, Meldry runs the homeserver, the protocol does the rest.
When Element or any client talks to your homeserver, it does one of four things:
/sync — a long-poll that returns everything new since the last request: new events in rooms, new invites, presence changes, to-device messages. Clients keep one /sync open at all times; the server holds it open for up to 30 seconds and then returns whatever arrived.PUT /rooms/{id}/send/{event_type}/{txn_id} — sends a new event (a message, a reaction, a redaction). The txn_id makes sends idempotent so retries don't duplicate.mxc:// URI.Everything is authenticated with a bearer access token obtained at login. See the Matrix client-server spec for the full API.
When your homeserver needs to send a message into a room that has members on another server, it:
The remote server doesn't trust the sender blindly — it verifies every event's signature and checks that the event's "auth chain" (the sequence of auth events that justify why this event is allowed at all) is valid according to the room's power-level rules.
If two servers add events concurrently, the state resolution algorithm picks a canonical ordering based on the events' auth_events and a deterministic tie-breaker. Both servers end up with the same final state.
Every event in a room contains a prev_events field listing the hashes of events it was sent in response to. With many participants across many servers, prev_events can point at multiple predecessors, forming a directed acyclic graph. Clients walk the DAG backwards to show you history; servers use it to detect and heal forks when federation catches up after a partition.
A room is a shared, replicated event log with auth rules. Every room has:
!abc123:server#general:serverRooms can be public (listed in the homeserver's directory) or private (invite-only). They're not scoped to a homeserver — a room that originated on matrix.org can have members on your-name.meldry.com, on kde.org, and on element.io all simultaneously, and every homeserver replicates its own copy of the events.
A space is a special kind of room whose "members" are other rooms and other spaces. Spaces are Matrix's answer to "I want a Slack workspace" or "I want a Discord server" — they group related rooms into a browseable hierarchy. You can nest spaces, mark some rooms as "suggested", and selectively share parts of a space with outsiders.
Under the hood a space is just a room with a specific room type (m.space) and m.space.child state events pointing at its children.