Skip to main content
zapo is built for long-lived, multi-session workloads. This page collects the operational decisions that matter once you move past a local prototype.

Persist credentials (don’t re-pair)

Production sessions must use a durable store for the auth and Signal domains, plus a stable sessionId across restarts. The in-memory store loses everything on exit, forcing a re-pair on every boot.
Changing sessionId orphans the previous credentials — treat it as the durable key for a device/account.

Choose a store backend

You can mix backends per domain (e.g. auth/signal in Postgres, caches in Redis). See Installation and the stores reference.

Graceful shutdown

Call disconnect() (never logout()) on shutdown — it flushes pending write-behind data and closes the socket without unlinking the device, so the next boot resumes from the store.
logout() unlinks the device server-side and clears stored state — it forces a full re-pair. Use it only to permanently disconnect, never as a shutdown hook.

Run many sessions

A single store can hold many independent accounts, each keyed by sessionId. Create one WaClient per account:
Each client pairs, reconnects, and emits events independently. Budget memory/CPU per session (each holds Signal state and in-memory caches), and shard across processes/hosts as you scale — one process per session is the simplest isolation model. See Multi-session deployments for the full operational guide.

Tune for throughput

  • Write-behind batches incoming message/thread/contact writes off the hot path. Tune writeBehind.maxPendingKeys / maxWriteConcurrency / flushTimeoutMs to your database. (config)
  • History sync (history.enabled) is on by default and adds a large initial download. Set it to false if you don’t persist mailbox/threads/contacts; set requireFullSync deliberately.
  • Bots that shouldn’t appear online: markOnlineOnConnect defaults to false, so bots are invisible on connect out of the box. Pass true only when you want a visible “online” presence.
  • Timeouts (iqTimeoutMs, keepAliveIntervalMs, deadSocketTimeoutMs, …) ship with production defaults — override only with a reason. (config)

Reconnection & error policy

zapo does not auto-reconnect — own the policy. Wire a backoff loop (Reconnection) and classify failures (Errors & disconnects) so you stop on fatal reasons (banned, not_authorized, logout) instead of hammering the server.

Logging

Use a structured logger in production:
pretty: false emits JSON lines suited to log aggregators. Drop to debug / trace only when investigating.

Security & versioning

  • Credentials are secrets. WaAuthCredentials holds the device keys — if you persist them outside the built-in store, encrypt at rest. (Authentication)
  • Never enable dangerous.* in production — those flags disable security checks. (config)
  • Versioning. zapo is 1.0 and follows semantic versioning — breaking changes only land in a new major. Use a version range or lockfile as usual, and review the changelog before major upgrades.
Last modified on June 1, 2026