How to configure Knex for a horizontally scaled system?

368 Views Asked by At

How should I configure Knex.js for a horizontally scaled system (Docker Swarm / Kubernetes) that uses a Postgres database. For each new process I add, the open connections to the database increases. The number of processes are not static, but I could make the number of processes I run static or semi static.

Is it recommended to use an external connection pooler like PgBouncer or similar to act as a middle man between the processes that uses Knex and the database, so that the system avoids having too many open connections directly to the database at the same time? From my understanding, this can degrade the DB performance if there are too many open connections to the DB and/or just hit the connection limit to the Database.

But since Knex handles it own pooling, mixing this with PgBouncer seems to not be a good solution. But at the same time, when I scale out the system, I get too many open connections to the DB.

When I tested using PgBouncer with my system that runs multiple Node processes all using Knex, then the PgBouncer connection limit or the pool limit was reached quickly. This was the PgBouncer config I used, the default config except I changed it to use transaction mode as I see recommended a lot:

max_client_conn = 100
default_pool_size = 20
pool_mode = transaction

For Knex I used this config

pool: {
  min: 2,
  max: 25,
}

So how should you configure Knex for a horizontally scaled system? Should I use a connection pooler like PbBouncer that all the processes connect to, or should each process handle their own connection pools?

It seems to me that the first solution would be better, since then the processes that experiences heavy load at a given time can use all the available resources, instead of limiting itself to not ruin it for others processes that might or might not need the DB at the same time.

EDIT: You need to know the max number of instances you might have and then calculate how many connections your database or pooler can handle.

If you use a connection pooler, it can mostly fix this issue, but you need to make sure your pooler will not pin all of the connections. If I remember correctly, Knex uses prepared statements for all non-raw requests, and this made our pooler pin all the requests, which meant the connections could not be shared and therefore ran out of available connections very quickly.

0

There are 0 best solutions below