Description
Evolution Go continuously creates new idle PostgreSQL connections in evogo_auth. The connections are not reused or closed after WhatsApp instance reconnects.
Over time, PostgreSQL reached its max_connections limit of 200 and started rejecting connections.
Environment
- Evolution Go version:
0.7.2
- Docker image:
evoapicloud/evolution-go:0.7.2
- Deployment: Docker
- Database: PostgreSQL
POSTGRES_AUTH_DB: PostgreSQL database evogo_auth
POSTGRES_USERS_DB: PostgreSQL database evogo_users
- Connected WhatsApp instances: 4
- Created but disconnected instances: 1
Observed behavior
Immediately after restarting the Evolution Go container, PostgreSQL showed approximately:
evogo_users: 1 idle connection
evogo_auth: 7 idle connections
About 18 minutes later, evogo_auth had 11 idle connections and continued growing:
datname | state | connections
------------+-------+------------
evogo_auth | idle | 11
evogo_users | idle | 1
Before the restart, the same behavior eventually consumed all 200 PostgreSQL connection slots.
The new connections originate from the Evolution Go container. New evogo_auth connections appear after instance disconnect/reconnect cycles and remain idle.
Temporary mitigation
I configured:
ALTER ROLE <evolution_db_user>
IN DATABASE evogo_auth
SET idle_session_timeout = '5min';
After restarting Evolution Go, PostgreSQL began terminating the old idle connections after approximately five minutes. This prevents unlimited accumulation, but it does not fix the underlying pool lifecycle.
Suspected cause
StartClient creates a new Whatsmeow SQL store container for every client start:
container, err = sqlstore.New(
context.Background(),
"postgres",
w.config.PostgresAuthDB,
dbLog,
)
Source:
https://github.com/evolution-foundation/evolution-go/blob/main/pkg/whatsmeow/service/whatsmeow.go
When a Disconnected event occurs, ReconnectClient removes the client from the runtime maps and starts it again. However, the previously created sqlstore.Container is not retained by the service and is not closed.
Therefore, every reconnection may create another PostgreSQL pool while the previous pool remains open.
Expected behavior
- PostgreSQL connections should be reused.
- Reconnecting an instance should not permanently increase the number of idle database connections.
- The number of PostgreSQL connections should be bounded by a shared pool, not by the number of reconnect attempts.
- Hundreds or thousands of WhatsApp instances should not require one independent PostgreSQL pool per instance.
Suggested solution
Create one shared PostgreSQL sql.DB and one shared sqlstore.Container during application startup, using the Whatsmeow NewWithDB API.
Inject the shared container into whatsmeowService.
StartClient should only call:
or:
It should not call sqlstore.New() for every instance start.
The shared pool should be closed only during application shutdown.
If separate containers must remain, Evolution Go should retain and explicitly close each container before replacing or deleting a client.
Additional note
The v0.7.2 changelog mentions that the upstream Whatsmeow PostgreSQL pool patch was replaced by the application-side NewWithDB approach. However, StartClient still appears to use sqlstore.New() for each instance.
Description
Evolution Go continuously creates new idle PostgreSQL connections in
evogo_auth. The connections are not reused or closed after WhatsApp instance reconnects.Over time, PostgreSQL reached its
max_connectionslimit of 200 and started rejecting connections.Environment
0.7.2evoapicloud/evolution-go:0.7.2POSTGRES_AUTH_DB: PostgreSQL databaseevogo_authPOSTGRES_USERS_DB: PostgreSQL databaseevogo_usersObserved behavior
Immediately after restarting the Evolution Go container, PostgreSQL showed approximately:
About 18 minutes later,
evogo_authhad 11 idle connections and continued growing:Before the restart, the same behavior eventually consumed all 200 PostgreSQL connection slots.
The new connections originate from the Evolution Go container. New
evogo_authconnections appear after instance disconnect/reconnect cycles and remain idle.Temporary mitigation
I configured:
After restarting Evolution Go, PostgreSQL began terminating the old idle connections after approximately five minutes. This prevents unlimited accumulation, but it does not fix the underlying pool lifecycle.
Suspected cause
StartClientcreates a new Whatsmeow SQL store container for every client start:Source:
https://github.com/evolution-foundation/evolution-go/blob/main/pkg/whatsmeow/service/whatsmeow.go
When a
Disconnectedevent occurs,ReconnectClientremoves the client from the runtime maps and starts it again. However, the previously createdsqlstore.Containeris not retained by the service and is not closed.Therefore, every reconnection may create another PostgreSQL pool while the previous pool remains open.
Expected behavior
Suggested solution
Create one shared PostgreSQL
sql.DBand one sharedsqlstore.Containerduring application startup, using the WhatsmeowNewWithDBAPI.Inject the shared container into
whatsmeowService.StartClientshould only call:or:
It should not call
sqlstore.New()for every instance start.The shared pool should be closed only during application shutdown.
If separate containers must remain, Evolution Go should retain and explicitly close each container before replacing or deleting a client.
Additional note
The v0.7.2 changelog mentions that the upstream Whatsmeow PostgreSQL pool patch was replaced by the application-side
NewWithDBapproach. However,StartClientstill appears to usesqlstore.New()for each instance.