Guide

Self-hosted team chat, without the weekend.

What a self-hosted chat stack actually contains, how the open source options differ, what hardware you need, and what it costs once you count the hours. Then three commands to run one.

Fluid Chat needs Postgres and nothing exotic. Redis is optional until you scale out.

1
hard dependency: Postgres
3
app processes
$6–15
a month for ~25 people
~1 hr
a month of maintenance

Self-hosted team chat is one of those categories where the software has been solid for years and the operational story is what actually decides whether you do it. This page is about the operational story: what you run, what it costs, how big a box you need, and where each of the open source options puts its sharp edges.

Why teams self-host chat

In practice there are four reasons, and they're worth separating because only some of them are good ones.

  1. 1Data residency and control. The messages have to be in a specific jurisdiction, on infrastructure you can point at. This is the reason that survives scrutiny — no SaaS contract fully substitutes for the data being on your disk.
  2. 2Network isolation. Air-gapped environments, defence, industrial, or anywhere the chat tool has to work when the internet doesn't.
  3. 3Cost at scale. Per-seat pricing compounds; a server doesn't. Past roughly 50 people the maths gets loud.
  4. 4Vendor independence. Pricing changes, acquisitions, region shutdowns and deprecated features are all things that happen to other people until they happen to you.

A reason that does not survive scrutiny: “it'll be cheaper because it's free.” Software licences are rarely the expensive part of self-hosting. The expensive part is the person who gets paged.

What a self-hosted chat stack actually contains

Most team chat systems decompose into the same five pieces. The differences between products are mostly about how many separate services each piece needs.

PieceWhat it doesIn Fluid Chat
DatabaseMessages, channels, users, membershipsPostgres — the only hard dependency
SearchFinding any of the above againAlso Postgres (full-text search)
RealtimePresence, typing, live deliverySocket.IO, optional Redis for fan-out
Object storageUploads and exportsAny S3-compatible store, MinIO included
Background jobsReminders, retention, exports, emailOne worker process

The open source options, honestly

Four serious choices, each good at something different. The architecture is the durable distinction — pricing pages get rewritten, database engines don't.

Fluid ChatMattermostRocket.ChatZulip
LanguageTypeScriptGoJavaScriptPython
DatabasePostgresPostgres / MySQLMongoDBPostgres
SearchPostgres FTSPostgres FTS or ElasticsearchMongoDB text or ElasticsearchPostgres FTS
Conversation modelChannels + threadsChannels + threadsChannels + threadsChannels + topics
Voice / videoNoYesYesVia integrations
Admin features gated by tierNoneSomeSomeSome (cloud)
Ops surfaceSmallMediumMedium–largeMedium

Choose Mattermost for the most established enterprise track record and the widest compliance story. Choose Rocket.Chat if you need voice, video and omnichannel in one deployment, and you're comfortable operating MongoDB. Choose Zulip if your team genuinely thinks in topics — its threading model is the strongest in the category and a legitimate reason to pick it over everything here. Choose Fluid for the smallest ops surface and no feature tiers at all.

Installing Fluid Chat

Three commands to a running workspace. The first account you create owns it, with #general and #random already in place.

Docker Compose
# clone, configure, rungit clone https://github.com/azianmike/fluid-chat.gitcd fluid-chat && cp .env.example .envdocker compose up  app       ready on http://localhost:3000  realtime  websockets on :3001  worker    jobs running  postgres  migrations applied

From there, the repo's docs cover SMTP, S3/MinIO, HTTPS and domains, backup, restore and upgrade — the install guide is the entry point.

Sizing and cost

Team chat looks like a heavy realtime workload and behaves like a light one. A busy 50-person team writes a few thousand messages a day — a rounding error for Postgres.

Team sizeStarting shapeRough monthly infrastructure
Up to ~251 vCPU / 2 GB, Postgres on the same box$6–15
25–1002 vCPU / 4 GB, managed Postgres$30–70
100–5002+ app processes, Redis, managed Postgres$100–250
500+Load-balanced app tier, Postgres with real IOPSScales with the database, not the headcount

Infrastructure figures are illustrative and depend entirely on your provider — the shape is the point, not the digits. The shape is: cost tracks usage, not headcount. A per-seat plan does the opposite, which is why the two lines cross and never uncross.

The cost people forget is time. Budget a few hours for the initial setup and TLS, then something like an hour a month for patching and upgrades. That's the real invoice.

The four ops jobs you're signing up for

  1. 1Backups. For Fluid that's a Postgres dump plus your object store — there's no second datastore holding half the messages. Then restore it once, on purpose, before you ever need to.
  2. 2TLS and domains. A reverse proxy in front of the app and the realtime port. This is where most self-hosting afternoons go; the repo has a doc for it.
  3. 3Upgrades. Migrations run on start. Read the upgrade doc, take a backup first, do it on a Tuesday.
  4. 4Patching the host. Not glamorous, entirely yours.

One database. Three processes. Two minutes.

Clone it and run docker compose up, or start on the free hosted version and migrate to your own infrastructure whenever you feel like it.

FAQ

Self-hosting, the practical questions.

What is the best self-hosted team chat?

Mattermost is the most established for enterprise deployments, Rocket.Chat bundles voice, video and omnichannel, Zulip has the strongest threading model, and Fluid Chat has the smallest operational surface with no features gated behind paid tiers. All four are open source and run on your own infrastructure; the right answer depends on whether you're optimising for compliance, feature breadth, conversation model or ops simplicity.

What do I need to run self-hosted team chat?

For Fluid Chat: Postgres 14+, Node 20+, and S3-compatible object storage. Redis is optional and only needed once you run more than one app or realtime process. Other platforms differ — Rocket.Chat needs MongoDB, and Mattermost and Zulip both use Postgres.

How much does self-hosted team chat cost?

For most small teams, the cost of a small VPS — often under $15 a month for up to about 25 people — plus a few hours of setup time and roughly an hour a month of maintenance. Cost tracks usage rather than headcount, which is the structural difference from per-seat SaaS pricing.

Is self-hosted chat more secure than cloud chat?

It's differently secure. You remove a third party from the trust boundary and take on host patching, TLS and backups yourself. Self-hosting is a genuine win for data residency and network isolation; it's a loss if nobody on the team has time to run it properly.

Do I need Kubernetes?

No. A single VPS running Docker Compose handles a team of dozens comfortably. Kubernetes becomes relevant when you want multiple app processes behind a load balancer, which for Fluid Chat also means adding Redis so realtime events fan out over pub/sub.

Can I move from hosted to self-hosted later?

With Fluid Chat, yes — the hosted app runs the same code as the repo, and full data export (JSONL, CSV and a file manifest) is included on the free plan, so nothing about the hosted version traps you in it.

Something not covered? Open an issue.

Run your own chat. It's a Tuesday, not a project.

Clone the repo onto a small server and you're done before lunch. Or use the free hosted version and keep the option open.