Your Strapi app starts, hangs for a minute, then dies with:
Knex: Timeout acquiring a connection. The pool is probably full.
Are you missing a .transacting(trx) call?This message is one of the least helpful errors in the Node ecosystem. It is generated by Knex, Strapi's query builder, and it fires whenever Knex waits longer than acquireConnectionTimeout for a usable connection. The message then guesses at a cause, a full pool or a missing transaction, and that guess is usually wrong.
In the overwhelming majority of Strapi cases, the pool is not full. Strapi cannot reach the database at all.
Knex asks the pool for a connection, the pool tries to create one, the TCP connection hangs because a firewall is dropping the packets, and 60 seconds later Knex reports the only thing it knows: it never got a connection.
Triage in the right order
1. Can anything reach the database from where Strapi runs?
Do this before touching a single config value. From the same machine, container, or dyno that runs Strapi:
# Is the port even open?
nc -zv your-db-host.example.com 5432
# PostgreSQL
psql "postgresql://USER:PASSWORD@your-db-host.example.com:5432/DBNAME" -c "select 1;"
# MySQL / MariaDB
mysql -h your-db-host.example.com -P 3306 -u USER -p -e "select 1;"If nc hangs, this is a network problem and no pool setting will fix it. The usual culprits:
- Your IP is not allowlisted. Managed Postgres on AWS RDS, Azure, Supabase, Neon, and DigitalOcean all default to denying inbound connections. This is the single most common cause, and it is what resolved the original forum thread: the poster's home IP had changed and was no longer in the allowlist.
- The security group or firewall rule targets the wrong source. An RDS security group that allows your laptop will not allow your ECS task.
- The database is in a private subnet and Strapi is not.
- A Docker network mismatch. Inside Compose,
localhostmeans the Strapi container, not the database container. Use the service name (postgres,db) as the host.
2. Read the database's own log
The database log tells you what Strapi's log cannot. Look for rejected connections, authentication failures, and "too many connections" errors. A refused connection that never reaches the server leaves no trace there at all, which is itself a useful signal that the problem is upstream in the network.
3. Check whether you have actually exhausted connections
If the network is fine and the database is reachable, then look at connection counts:
-- PostgreSQL
SELECT count(*), state FROM pg_stat_activity
WHERE datname = 'your_db' GROUP BY state;
SHOW max_connections;Small managed instances are stingy. A Supabase free-tier pooler or an RDS db.t3.micro may cap you well below what several Strapi replicas plus your migrations plus your local psql session are trying to open at once.
Now the configuration
Strapi's pool options live under connection.pool in config/database, and are passed straight to Tarn.js via Knex. The defaults:
| Option | Default |
|---|---|
min | 2 |
max | 10 |
acquireTimeoutMillis | 60000 |
createTimeoutMillis | 30000 |
idleTimeoutMillis | 30000 |
acquireConnectionTimeout (on connection, not pool) | 60000 |
export default ({ env }) => ({
connection: {
client: 'postgres',
connection: {
host: env('DATABASE_HOST', '127.0.0.1'),
port: env.int('DATABASE_PORT', 5432),
database: env('DATABASE_NAME', 'strapi'),
user: env('DATABASE_USERNAME', 'strapi'),
password: env('DATABASE_PASSWORD', 'strapi'),
ssl: env.bool('DATABASE_SSL', false),
},
pool: {
min: env.int('DATABASE_POOL_MIN', 2),
max: env.int('DATABASE_POOL_MAX', 10),
},
acquireConnectionTimeout: env.int('DATABASE_CONNECTION_TIMEOUT', 60000),
},
});Two adjustments are genuinely worth making.
Running in Docker or on a serverless platform: set min: 0. The Strapi docs call this out explicitly. Docker and most serverless runtimes kill idle TCP connections. If the pool insists on keeping two connections alive, it hands out dead sockets and you get intermittent timeouts under low traffic, the confusing kind that only appear after the app has been quiet for a few minutes.
pool: { min: 0, max: 10 },Running several replicas: divide max by the replica count. Four Strapi instances at max: 10 will try to open 40 connections. If the database allows 20, some of them will always be waiting.
What not to do
Forum threads on this error converge on a config block with every timeout cranked to five or six figures:
// Don't cargo-cult this
acquireConnectionTimeout: 1000000,
pool: {
min: 0, max: 1,
acquireTimeoutMillis: 300000,
createTimeoutMillis: 300000,
destroyTimeoutMillis: 300000,
},This does not fix anything. It makes a broken deploy hang for five minutes instead of one before failing, and max: 1 serialises every query in your application. If raising a timeout appears to help, what you have actually found is a slow connection handshake, usually TLS negotiation against a distant database, and the fix is to move the database closer or fix the TLS config, not to wait longer.
Special cases worth knowing
Connection poolers. Supabase, PgBouncer, and RDS Proxy sit in front of Postgres in transaction-pooling mode. Point Strapi at the pooler's port (6543 on Supabase, not 5432), keep Strapi's own max low, and be aware that prepared statements and session-level features behave differently through a transaction pooler.
SSL. A database that requires SSL will hang or reject if Strapi connects without it. Set ssl: true, and for providers with self-signed certificates:
ssl: env.bool('DATABASE_SSL', false) && {
rejectUnauthorized: env.bool('DATABASE_SSL_SELF', false),
},Long-running custom queries. If you have written a controller that iterates records and issues a query per record without releasing connections, you can genuinely exhaust the pool. This is the case the error message was written for, and it is the rarest one. Look for strapi.db.connection usage in your own code and wrap multi-step work in a transaction.
The 30-second version
nc -zv <db-host> <port>from the machine running Strapi. If it hangs, fix networking, not config.- Check the allowlist / security group. Your IP probably changed.
- Read the database log.
- In Docker or serverless, set
pool.min: 0. - Only tune
pool.maxonce you have confirmed the connection count is actually the limit.




