ChatMail load tuning: server changes for sustained traffic

Server-side changes made to eijo.im (lca-01) while load testing with 50 concurrent Delta Chat user pairs.

Postfix

default_process_limit 100 → 500. The default caps all Postfix service types (smtpd, lmtp, cleanup, etc.) at 100 processes. With 150 concurrent SMTP connections (50 pairs × 3-slot ring buffer), LMTP delivery workers were starved.

postconf -e 'default_process_limit = 500'
systemctl reload postfix

default_destination_concurrency_limit 20 → 100. Controls how many messages Postfix delivers to a single destination concurrently. At 20, messages queued behind each other waiting for LMTP slots, adding seconds of tail latency (p99 went from 7.3s to sub-1s after this change).

postconf -e 'default_destination_concurrency_limit = 100'
systemctl reload postfix

Dovecot

imap_hibernate_timeout 30s → 5min. Dovecot hibernates idle IMAP connections to save memory. At 30 seconds, connections were being hibernated mid-IDLE and missing EXISTS notifications when LMTP delivered new mail. Messages arrived but receivers never saw them.

# /etc/dovecot/dovecot.conf
imap_hibernate_timeout = 5min
systemctl restart dovecot

mtail

The postfix_noqueue counter matched all NOQUEUE log lines, including benign SASL authentication announcements that Postfix emits when a client authenticates before sending. The ring buffer warming 3 connections per sender produced a flood of false positives on the Grafana error panel.

# Before (matches auth announcements)
/postfix\/.*NOQUEUE/

# After (matches only actual rejections)
/NOQUEUE: reject:/
systemctl restart mtail

Result

Before tuning: 48 lost messages per 6794 sent, p99 7.3s. After tuning: 0 lost per 4137 sent, p50 0.4s, 0 failures.