Toggling Mattermost Read Receipts: Performance, Privacy, and a 3‑Node Cluster Walk‑through
Step-by-step guide to enabling Mattermost read receipts via System Console or mmctl, with performance numbers, privacy controls, and a 3-node cluster rollout example.
11 Mar 2026, 21:45 UTC

The problem: extra write latency on busy channels
When a team runs a high‑traffic public channel, every message already generates a write to the posts table and a WebSocket broadcast. Enabling read receipts adds a second write (a row in message_read) and a tiny real‑time push for each recipient. In a 3‑node Mattermost cluster that can push the database write load up 5‑10 % and increase latency for the last user in a long thread.
What the flag actually does
The System Console exposes a single checkbox: Settings → Advanced Settings → Enable Read Receipts. When checked, Mattermost (6.0+) creates a message_read entry each time a user opens a channel and the client acknowledges the newest post. A blue tick appears next to the message timestamp. The feature is purely additive—no schema migrations are required beyond the existing message_read table.
Impact on traffic, storage, and privacy
- Write load: each delivered message incurs one extra INSERT. On a 1-million-user instance this translates to roughly 50 MB of additional disk per year.
- WebSocket traffic: a small JSON payload (
{"type":"read_receipt","post_id":"…","user_id":"…"}) is pushed to the reading user's session. - Privacy controls: admins can disable globally; users can opt out per channel via Channel Settings → Privacy → Show read receipts.
Worked example: enabling read receipts on a 3‑node cluster
Assume three application nodes (mm-app-01, mm-app-02, mm-app-03) sharing a single PostgreSQL database. All nodes run Mattermost 7.10 as the mattermost system user.
1. Verify the current setting
# Run on any node (requires read access to config.json)
cat /opt/mattermost/config/config.json | jq '.ServiceSettings.EnableReadReceipts'
Expected output: false (default).
2. Enable via mmctl (preferred for clusters)
# Run on each node as the mattermost user
mmctl config set ServiceSettings.EnableReadReceipts true
mmctl writes the change to config.json and signals the running process to reload. No full restart is required, but a rolling restart guarantees all nodes pick up the new value cleanly.
3. Rolling restart (zero-downtime)
- Drain traffic from
mm-app-01(e.g., remove from load balancer). systemctl restart mattermoston that node.- Confirm health endpoint returns
200 OK(curl -s http://localhost:8065/api/v4/system/ping). - Return node to the pool; repeat for
mm-app-02andmm-app-03.
Permissions: the mattermost user must have write access to /opt/mattermost/config/ and permission to restart the systemd unit.
4. Verify the feature works
- Open the System Console on any node → Settings → Advanced Settings → confirm Enable Read Receipts is checked.
- In a test channel, send a message from user A, then open the channel as user B. A blue tick should appear next to the timestamp.
- Check the database:
SELECT * FROM message_read WHERE post_id = '<post-id>' AND user_id = '<user-b-id>';– one row should exist.
Trade-offs and monitoring
| Benefit | Cost / Risk |
|---|---|
| Engagement visibility for product teams | +5-10 % write throughput on the primary DB |
| User-level opt-out respects privacy | Additional ~50 MB/yr per million users in message_read |
| Real-time feedback in UI | Potential lag on slow inter-node links (WebSocket push) |
If your PostgreSQL instance runs on a single node with default max_wal_size and checkpoint_completion_target, the extra inserts can increase checkpoint frequency. Consider raising max_wal_size or moving to a read-replica for reporting queries.
Actionable next steps
- Enable the flag in a staging cluster first; run a load test (e.g.,
hey -c 100 -n 10000against/api/v4/posts) and compare latency with the flag off. - Add a Prometheus alert on
mattermost_db_write_latency_seconds> 200 ms to catch regressions early. - Schedule a monthly
DELETE FROM message_read WHERE create_at < NOW() - INTERVAL '90 days';if your retention policy permits. - Document the per-channel opt-out path in your internal runbook so support can guide users who request privacy.
By toggling the single System Console switch—and confirming the change across all three nodes—you gain read-receipt visibility while keeping the performance impact measurable and bounded.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.