Why We Store WhatsApp Auth in PostgreSQL
One of the most common complaints about WhatsApp automation tools is session instability. You connect your number, everything works for a few hours, then the container restarts and you're back to scanning QR codes. We solved this in Wataki by storing the entire auth state in PostgreSQL.
How WhatsApp multi-device auth works
When you scan the QR code, the WhatsApp client performs a key exchange that produces a set of cryptographic credentials — identity keys, session keys, and pre-keys. These credentials are what allow your device to send and receive messages without the phone being online.
Most libraries (including Baileys, which Wataki uses under the hood) store this state in local files by default. That works fine for a single-process script on your laptop, but it falls apart in production: containers are ephemeral, disks are not shared across replicas, and a failed deploy means re-linking every instance.
The PostgreSQL auth store
Wataki implements a custom auth state adapter that maps Baileys' storage interface to PostgreSQL tables. When Baileys writes a new pre-key or updates session state, the change goes directly to the database instead of the filesystem.
This gives us several advantages:
- Survive restarts. When a container comes back up, Wataki reads the auth state from PostgreSQL and reconnects to WhatsApp without any user interaction.
- Scale horizontally. Multiple API servers can access the same auth state since it lives in a shared database rather than local disk.
- Backup and restore. Auth state is included in regular database backups. If something goes wrong, you can point-in-time recover to a known good state.
- Audit trail. Every change to auth state is a database write that can be logged and monitored like any other data mutation.
Implementation details
The auth state is stored per-instance in a dedicated table. Each row contains the instance ID, a key type (identity, pre-key, session, etc.), the key ID, and the serialized key data as a JSONB column.
On startup, Wataki loads all keys for the instance into memory for fast lookups — Baileys reads keys frequently during message encryption and decryption. Writes are batched and flushed to PostgreSQL asynchronously, so the encryption hot path is never blocked by a database round trip.
The result
Since shipping this change, we've seen zero reports of unexpected disconnections due to lost auth state. Instances stay connected through deploys, container rescheduling, and even database failovers (as long as the failover completes within WhatsApp's timeout window).
If you're building anything on Baileys and struggling with session persistence, consider moving your auth state to a database. The upfront work pays for itself many times over in operational reliability.