diff --git a/src/Defaults/index.ts b/src/Defaults/index.ts index 5453c4e5..0c49914c 100644 --- a/src/Defaults/index.ts +++ b/src/Defaults/index.ts @@ -87,6 +87,12 @@ export const DEFAULT_CONNECTION_CONFIG: SocketConfig = { enableCTWARecovery: true, // Enable interactive messages (buttons, lists, templates, carousel) enableInteractiveMessages: true, + // Clear stale routingInfo on every socket creation so the WhatsApp load balancer + // assigns a fresh, healthy edge server after any restart (pm2, server reboot, deploy). + // The server always sends a new routingInfo during the connection handshake, so the + // old value is never needed. Keeping it can cause slow or unstable sessions when the + // previous edge server is overloaded or has stale state. + clearRoutingInfoOnStart: true, options: {}, appStateMacVerification: { patch: false, diff --git a/src/Socket/socket.ts b/src/Socket/socket.ts index 342f1d5f..763fb18f 100644 --- a/src/Socket/socket.ts +++ b/src/Socket/socket.ts @@ -178,6 +178,15 @@ export const makeSocket = (config: SocketConfig) => { throw new Boom('Mobile API is not supported anymore', { statusCode: DisconnectReason.loggedOut }) } + // If clearRoutingInfoOnStart is enabled, discard the stored routing hint so WhatsApp + // assigns a fresh edge server on this connection. This fixes sessions that became slow + // after a pm2 restart because the previous edge server retained stale state. + // Signal keys and auth credentials are NOT affected — no QR re-scan is needed. + if (config.clearRoutingInfoOnStart && authState?.creds?.routingInfo) { + logger.info('clearRoutingInfoOnStart: discarding stored routingInfo to force fresh edge server assignment') + authState.creds.routingInfo = undefined + } + if (url.protocol === 'wss' && authState?.creds?.routingInfo) { url.searchParams.append('ED', authState.creds.routingInfo.toString('base64url')) } @@ -500,6 +509,13 @@ export const makeSocket = (config: SocketConfig) => { const ev = makeEventBuffer(logger) + // Persist the routingInfo clearing so the consumer's saveCreds() writes the clean state to disk. + // This ensures that if the process restarts again before the server assigns new routingInfo, + // the stale value is not reused. + if (config.clearRoutingInfoOnStart && !authState?.creds?.routingInfo) { + ev.emit('creds.update', authState.creds) + } + const { creds } = authState // add transaction capability const keys = addTransactionCapability(authState.keys, logger, transactionOpts) diff --git a/src/Types/Socket.ts b/src/Types/Socket.ts index 6f0f22bf..7804c96b 100644 --- a/src/Types/Socket.ts +++ b/src/Types/Socket.ts @@ -141,6 +141,26 @@ export type SocketConfig = { */ enableInteractiveMessages: boolean + /** + * When true, clears the `routingInfo` stored in credentials before connecting. + * + * `routingInfo` is a hint that directs the socket to reconnect to the same + * WhatsApp edge server used in the previous session. After a code update or + * server-side configuration change, the old edge server may retain stale state + * (throttling, queued messages, etc.) that causes persistent slowness even with + * fresh code — only solvable by re-scanning the QR code. + * + * Setting this to `true` forces WhatsApp to assign a fresh edge server on the + * next connection, equivalent to the clean state you get after a QR re-scan, + * but without invalidating the session or Signal keys. + * + * Recommended usage: enable this option in your `startSock()` call right after + * deploying a new version, then disable it on subsequent reconnections. + * + * @default false + */ + clearRoutingInfoOnStart: boolean + /** * Returns if a jid should be ignored, * no event for that jid will be triggered.