Skip to content
Go back

Matrix: Synapse vs Dendrite vs Conduit

By SumGuy 12 min read
Matrix: Synapse vs Dendrite vs Conduit

Matrix is the self-hosted Slack alternative that doesn’t lock you in

You want a chat platform that lives in your homelab, works with everyone (not just your Matrix friends), and doesn’t cost you a kidney in server hardware. That’s Matrix: a federated, encrypted-by-default messaging protocol. Think IRC meets Slack, but open source and owned by the community instead of some VC-funded startup that’ll rebrand and enshittify it in three years.

The problem? Matrix is just the protocol. You need a server to run it. And here’s where things get interesting: there are three major implementations, each written in a different language, each with its own philosophy about what a Matrix homeserver should be.

So which one should you run? That depends on your use case. Let’s break it down.

The Matrix protocol in 90 seconds

You don’t need to be a protocol wizard, but knowing the basics helps you understand why these servers differ.

Matrix is event-based. Every message, reaction, room state change — that’s an event. Events get signed, stored, and replicated across servers via federation. Your @you:homeserver.com address can talk to @friend:otherserver.com just like they’re in the same room. Servers trust each other through cryptographic signatures, not permissions lists.

Rooms are the atomic unit — like Slack channels but way more flexible. They support encryption (E2EE), state events, and reactions. User accounts live on one homeserver (yours). Everything else — rooms, direct messages, communities — is federated.

That federation is the whole point. You control your data. You’re not renting a seat on someone’s SaaS platform.

Synapse: The mature, feature-complete road hog

Synapse is the reference implementation. It’s what the Matrix core team originally built. Everyone else is chasing parity with Synapse because Synapse supports basically everything the protocol can do.

The good:

The bad:

Who should run Synapse?

Dendrite: The polished-up younger sibling

Dendrite is the rewrite. The Matrix team learned from Synapse and built Dendrite in Go, treating it as a chance to rethink the architecture. It’s componentized — the client API, federation, media storage, and room state can run as separate services. You can scale horizontally.

The good:

The bad:

Who should run Dendrite?

Conduit: The lean, opinionated alternative

Conduit is written in Rust. It’s a single binary. It doesn’t try to be Synapse. Instead, it asks: “What’s the minimum viable homeserver?” and builds exactly that.

The good:

The bad:

Who should run Conduit?

Head-to-head comparison

FeatureSynapseDendriteConduit
LanguagePythonGoRust
Memory (idle)300-500 MB150-250 MB20-50 MB
Memory (active)2-6+ GB400-800 MB50-150 MB
Startup time30-60s2-5s1-2s
Room versionsAllAllAll modern
E2EEYesYesYes
BridgesExtensive (mautrix-*, Bifrost)Most workLimited (some incompatibilities)
Admin APIFull-featuredPartialMinimal
WidgetsYesPartialNo
Polylith/scalingNot designedYes (multiple components)No (single binary)
ConfigurationComplex (many options)ModerateSimple (opinionated defaults)
Community sizeLargestGrowingSmallest
Single-user focusNot reallyNot reallyYes

Installation and deployment

Let’s get concrete. Here’s how you’d run each in Docker.

Synapse with Docker Compose

docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: synapse
POSTGRES_USER: synapse
POSTGRES_PASSWORD: your_secure_password
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
synapse:
image: matrixdotorg/synapse:latest
environment:
SYNAPSE_SERVER_NAME: example.com
SYNAPSE_REPORT_STATS: 'no'
LD_PRELOAD: /usr/lib/x86_64-linux-gnu/libjemalloc.so.2
volumes:
- synapse_data:/data
ports:
- "127.0.0.1:8008:8008"
depends_on:
- postgres
restart: unless-stopped
volumes:
postgres_data:
synapse_data:

Synapse requires PostgreSQL. Running it is straightforward, but initialization is a multi-step dance — you need to generate a config, create admin users with registration tokens, and tune settings.

Dendrite with Docker Compose

docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: dendrite
POSTGRES_USER: dendrite
POSTGRES_PASSWORD: your_secure_password
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
dendrite:
image: matrixdotorg/dendrite:latest
environment:
TZ: UTC
volumes:
- dendrite_data:/var/lib/dendrite
- /path/to/dendrite.yaml:/etc/dendrite/dendrite.yaml:ro
ports:
- "127.0.0.1:8008:8008"
depends_on:
- postgres
restart: unless-stopped
volumes:
postgres_data:
dendrite_data:

Dendrite also uses PostgreSQL. The config is simpler than Synapse because there are fewer knobs to turn. Still, you’ll need to generate a config and register users through the admin API.

Conduit with Docker Compose

docker-compose.yml
version: '3.8'
services:
conduit:
image: matrixconduit/matrix-conduit:latest
environment:
ROCKET_ADDRESS: 0.0.0.0
ROCKET_PORT: 6167
CONDUIT_SERVER_NAME: example.com
CONDUIT_ALLOW_REGISTRATION: 'true'
volumes:
- conduit_data:/var/lib/matrix-conduit
ports:
- "127.0.0.1:6167:6167"
restart: unless-stopped
volumes:
conduit_data:

Conduit is beautifully simple. No external database. It uses RocksDB internally. Environment variables for config. Done.

Reverse proxy: Caddy for all three

All three need a reverse proxy for TLS and .well-known federation endpoints. Here’s a Caddy config that works with any of them:

Caddyfile
matrix.example.com {
reverse_proxy localhost:8008
}
example.com {
redir /.well-known/matrix/server matrix.example.com:443
redir /.well-known/matrix/client {
status 200
body {"m.homeserver":{"base_url":"https://matrix.example.com"}}
}
}

(If using Conduit, change port 8008 to 6167.)

Managing users and registration

Once your server is running, you’ll want to create users.

Synapse: Registration tokens

Terminal window
# Generate a one-time registration token (valid for 24 hours by default)
docker exec synapse_container register_new_matrix_user \
-u username \
-p password \
-a \
http://localhost:8008
# Or with a token for share-based registration
curl -X POST http://localhost:8008/_synapse/admin/v1/registration_tokens/new \
-H "Authorization: Bearer your_admin_token"

Dendrite: Admin API

Terminal window
# Dendrite user creation via admin endpoint
curl -X POST http://localhost:8008/_dendrite/admin/v2/users \
-H "Content-Type: application/json" \
-d '{
"user_id": "@username:example.com",
"password": "password",
"admin": false
}'

Conduit: Admin panel or direct API

Conduit ships with a minimal web admin panel and supports user creation via the standard Matrix APIs.

Terminal window
# Create user via Matrix register endpoint (if registration is open)
curl -X POST http://localhost:6167/_matrix/client/r0/register \
-H "Content-Type: application/json" \
-d '{
"user_id": "username",
"password": "password",
"initial_device_display_name": "Desktop"
}'

The federation reality check

All three servers federate. But federation is hard. Here’s what to expect:

For a homelab? All three federate just fine. You won’t notice the difference unless you’re in mega-sized rooms or have thousands of users.

Bridges: Talking to Discord, Slack, IRC

Want your Matrix room to mirror Discord? Or IRC? That’s what bridges do.

Synapse: Full ecosystem. mautrix-discord, mautrix-slack, mautrix-telegram, Bifrost (for everything), heisenbridge (for IRC). All tested and documented.

Dendrite: Most bridges work, but you’ll hit edge cases. The admin APIs differ just enough that some bridge setup scripts break. Doable, but rough.

Conduit: Bridges are spotty. Some work great (mautrix-discord is fine). Others assume Synapse-specific APIs. Before deciding on Conduit, check if your target bridge is compatible.

Encryption: E2EE and key backups

All three support encryption out of the box. Clients encrypt messages client-side; servers can’t read them.

For personal/family use, don’t overthink this. All three are fine.

Recommendations by use case

Solo user on a Raspberry Pi or VPS:Conduit. 20 MB RAM, single binary, no fuss. You don’t need every Synapse feature. Just chat.

Family of 4-8 people:Conduit or Dendrite. Conduit if you want dead-simple deployment and low power. Dendrite if you want more feature parity with Synapse without the RAM overhead.

Small community (10-50 people):Dendrite or Synapse. Dendrite if you’re budget-conscious and can tolerate some rough edges. Synapse if you need every feature and have hardware to spare.

Medium community (50-500 people) with bridges to other platforms:Synapse. The bridge ecosystem is too good to pass up. If your community spans Matrix, Discord, IRC, and Slack simultaneously, Synapse is your only bulletproof choice.

Anything larger or mission-critical:Synapse on a beefy server, probably in polylith mode (multiple services) or even multiple Synapse instances behind a load balancer. By that point, you’re not running a homelab anymore — you’re running infrastructure.

Final thoughts

Matrix is the chat protocol that respects your data. But the server you run matters.

Synapse is the safe choice if you have the hardware and want every feature. Dendrite is the future — it’s getting faster and more complete every release. Conduit is the minimalist’s win if you’re willing to accept intentional limitations.

No wrong choice here. Pick the one that matches your hardware and your patience for rough edges. And honestly? All three are simpler to run than you’d think. Pick one, spin it up in Docker, and get chatting.

Your friends will thank you. Your ISP’s upload bandwidth less so.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Next Post
ModSecurity vs Coraza WAF

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts