From a96dc335ab696ddb1485484989bd0a806dbf9d78 Mon Sep 17 00:00:00 2001 From: Weiko Date: Mon, 27 Jul 2026 10:58:41 +0200 Subject: [PATCH] fix: apply configured pool size to core database (#23322) ## Context `PG_POOL_MAX_CONNECTIONS` is the server setting for the maximum number of PostgreSQL clients in a connection pool. The workspace primary and replica data sources already apply this setting, but the core TypeORM data source did not. Without an explicit `poolSize`, `node-postgres` uses its default limit of 10. As a result, deployments configured with a larger pool still kept the core pool at 10 connections per server process. During bursts of core database work, requests could therefore wait for a local pool connection even when PostgreSQL itself still had available capacity. That acquisition queue adds latency before the query starts, so database-level utilization alone does not reveal the bottleneck. ## What changes The core data source now applies: ```ts poolSize: Number(process.env.PG_POOL_MAX_CONNECTIONS ?? 10) ``` This makes the core data source consistent with the workspace data sources and with the documented meaning of `PG_POOL_MAX_CONNECTIONS`. ## Expected impact Deployments that configure a value above 10 can use that capacity for core database operations instead of queueing behind the driver's default limit. This targets short acquisition spikes affecting operations backed by the core database. The pool remains lazy, so this changes the maximum number of connections available to each process, it does not eagerly open every configured connection. ## Safety - Deployments without `PG_POOL_MAX_CONNECTIONS` keep the previous limit of 10. - Query behavior, transaction behavior, and timeouts are unchanged. - Workspace pool configuration is unchanged. - Operators remain responsible for choosing a value compatible with their total PostgreSQL connection budget and maximum server replica count. ## Scope This removes an unintended local connection-pool bottleneck. It does not address the source of synchronized database bursts, which should be handled separately by reducing unnecessary work. ## Testing Added a regression test that loads the core data source with `PG_POOL_MAX_CONNECTIONS=40` and verifies that TypeORM receives `poolSize: 40`. Review in cubic --- .../typeorm/core/core.datasource.spec.ts | 21 +++++++++++++++++++ .../database/typeorm/core/core.datasource.ts | 1 + 2 files changed, 22 insertions(+) create mode 100644 packages/twenty-server/src/database/typeorm/core/core.datasource.spec.ts diff --git a/packages/twenty-server/src/database/typeorm/core/core.datasource.spec.ts b/packages/twenty-server/src/database/typeorm/core/core.datasource.spec.ts new file mode 100644 index 0000000000..c02fe74016 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm/core/core.datasource.spec.ts @@ -0,0 +1,21 @@ +describe('typeORMCoreModuleOptions', () => { + const originalPoolMaxConnections = process.env.PG_POOL_MAX_CONNECTIONS; + + afterEach(() => { + if (originalPoolMaxConnections === undefined) { + delete process.env.PG_POOL_MAX_CONNECTIONS; + } else { + process.env.PG_POOL_MAX_CONNECTIONS = originalPoolMaxConnections; + } + jest.resetModules(); + }); + + it('uses the configured maximum pool size', async () => { + process.env.PG_POOL_MAX_CONNECTIONS = '40'; + + const { typeORMCoreModuleOptions } = + await import('src/database/typeorm/core/core.datasource'); + + expect(typeORMCoreModuleOptions.poolSize).toBe(40); + }); +}); diff --git a/packages/twenty-server/src/database/typeorm/core/core.datasource.ts b/packages/twenty-server/src/database/typeorm/core/core.datasource.ts index 88d5163628..5a09488262 100644 --- a/packages/twenty-server/src/database/typeorm/core/core.datasource.ts +++ b/packages/twenty-server/src/database/typeorm/core/core.datasource.ts @@ -54,6 +54,7 @@ export const typeORMCoreModuleOptions: TypeOrmModuleOptions = { ], synchronize: false, migrationsRun: false, + poolSize: Number(process.env.PG_POOL_MAX_CONNECTIONS ?? 10), migrationsTableName: '_typeorm_migrations', metadataTableName: '_typeorm_generated_columns_and_materialized_views', // The TypeORM migration system is frozen — historical migrations live in