Zulip is the most intellectually interesting product in this category. Its topic model is a genuine improvement on how everyone else organises conversation, and it is also the single biggest reason teams bounce off it. Comparing it to Fluid Chat is really one question wearing a costume: do you want your team to learn a new way to talk?
The one-paragraph answer
Choose Zulip if conversations in your team routinely get lost in busy channels, if you're async across timezones, or if you run an open source community where people need to catch up on three days of discussion without reading all of it. Choose Fluid Chat if your team already thinks in Slack's channels-and-threads model and you'd rather change the invoice than the habits.
How the topic model actually differs
In Slack — and in Fluid, and in Mattermost and Rocket.Chat — a channel is a stream of messages, and a thread is an optional side-branch hanging off one of them. Threads are opt-in, which means in practice they're used inconsistently, which means busy channels interleave four conversations at once and you reconstruct them by vibes.
In Zulip, every message belongs to a topic inside a channel. Topics aren't optional and they aren't attached to a parent message — they're a first-class, lightweight subject line. The result is that catching up on a busy channel means reading topic by topic, and each one is coherent.
The cost is adoption. Topics require a small ongoing discipline from every person: naming the thing you're about to talk about, before you talk about it. Teams that adopt it become evangelists. Teams that don't end up with a thousand topics called “question” and a slow drift back to whatever they used before.
Where they differ
| Fluid Chat | Zulip | |
|---|---|---|
| Backend | TypeScript / Next.js 15 | Python / Django |
| Database | Postgres | Postgres |
| Conversation model | Channels + optional threads | Channels + mandatory topics |
| Learning curve from Slack | Effectively none | Real, and worth it if it lands |
| Search | Postgres full-text, operators | Postgres full-text, extensive operators |
| Native mobile apps | No (responsive web) | iOS and Android |
| Voice / video | No | Via integrations |
| Self-hostable | Yes | Yes |
| Pricing model | $0, hosted or self-hosted | Self-hosted free; Cloud has paid tiers |
| Admin features gated by tier | None | Some on Cloud |
Zulip offers free Cloud plans to open source projects, academic groups and some non-profits, which is a genuinely good policy — see zulip.com/plans for current terms.
Two Postgres apps, different shapes
Both projects made the same good decision about storage: Postgres holds the data and the full-text search index, so there's no separate search cluster in the default deployment. If you like that property — and you should, it's the single biggest determinant of how annoying a self-hosted chat system is to operate — either one gives it to you.
Zulip's installer is mature and opinionated; it will set up a working production deployment on a fresh Ubuntu box with impressive thoroughness. Fluid's path is Docker Compose and three processes. Both are firmly in the “an afternoon, not a project” category.
What Fluid gives you that Zulip's free Cloud doesn't
Self-hosted Zulip is generous. Zulip Cloud, like most cloud products, has tiers. Fluid's hosted version has the same features as its self-hosted version, because there's only one version:
- Unlimited people and unlimited history, hosted, at $0.
- Audit log, retention policies, guest scoping and per-workspace read-only mode, included.
- Scoped API keys with per-key rate limits, rotation and expiry.
- Full data export — JSONL, CSV and a file manifest — on the free plan.
- No card field, no trial clock, no upgrade prompt.
And what Zulip has that Fluid doesn't: native mobile apps, a much longer track record, a larger community, and — most importantly — the topic model, if that's what you came for.
Channels and threads, done completely.
If the topic model isn't the thing you're switching for, Fluid gives you the familiar model with none of the billing. Start free in the browser or on your own Postgres.
How to decide, concretely
- 1Ask whether your channels are actually broken. If people can follow #engineering fine, topics solve a problem you don't have, and you're paying an adoption cost for nothing.
- 2Check your async ratio. The more your team spans timezones, the more Zulip's model pays for itself — catching up is where it shines.
- 3Be honest about discipline. Topics need naming. If your team can't be persuaded to use threads consistently today, they will not name topics tomorrow.
- 4Then pick on the boring stuff — mobile apps, hosting model, pricing — because at that point the architectures are close enough that operations decide it.