Choosing a Message Queue on Zerops
Use NATS for most cases (simple, fast, JetStream persistence). Use Kafka only for enterprise event streaming with guaranteed ordering and unlimited retention.
Decision Matrix
| Need | Choice | Why |
|---|---|---|
| General messaging | NATS (default) | Simple auth, JetStream built-in, fast |
| Enterprise event streaming | Kafka | SASL auth, 3-broker HA, unlimited retention |
| Lightweight pub/sub | NATS | Low overhead, 8MB default messages |
| Event sourcing / audit logs | Kafka | Indefinite topic retention, strong ordering |
NATS (Default Choice)
- Ports: 4222 (client), 8222 (HTTP monitoring)
- Auth: user
zerops+ auto-generated password - Connection — two supported patterns, pick ONE:
- Separate env vars (recommended, works with every NATS client library): pass
servers: ${hostname}:${port}plususer: ${user}, pass: ${password}as client-side connect options. The servers list stays credential-free. - Opaque connection string: pass
${connectionString}directly as the servers option — the platform builds a correctly-formatted URL with embedded auth that the NATS server expects.
- Separate env vars (recommended, works with every NATS client library): pass
- JetStream: Enabled by default (
JET_STREAM_ENABLED=1) - Storage: Up to 40GB memory + 250GB file store
- Max message: 8MB default, 64MB max (
MAX_PAYLOAD) - Health check:
GET /healthzon port 8222 - Config changes require restart (no hot-reload)
Kafka
- Port: 9092 (SASL PLAIN auth)
- Auth:
user+passwordenv vars (auto-generated) - Bootstrap:
${hostname}:9092 - HA: 3 brokers, 6 partitions, replication factor 3
- Storage: Up to 40GB RAM + 250GB persistent
- Topic retention: Indefinite (no time or size limits)
- Schema Registry: Port 8081 (if enabled)
Gotchas
- NATS config changes need restart: No hot-reload — changing env vars requires service restart
- Kafka single-node has no replication: 1 broker = 3 partitions but zero redundancy
- NATS JetStream HA sync interval: 1-minute sync across nodes — brief data lag possible
- Kafka SASL only: No anonymous connections — always use the generated credentials
- NATS authorization violation from a hand-composed URL: do not build a
nats://user:pass@host:4222URL from the separate env vars. Most NATS client libraries will parse the embedded credentials AND separately attempt SASL with the same values, producing a double-auth that the server rejects withAuthorization Violationon the first CONNECT frame (symptom: startup crash, no successful subscription). Use either the separate env vars passed as connect options (credential-free servers list) or the opaque${connectionString}the platform builds for you — both patterns in the Connection section above avoid the double-auth path.