diff --git a/apps/dokploy/__test__/db/pool-options.test.ts b/apps/dokploy/__test__/db/pool-options.test.ts new file mode 100644 index 0000000000..6271e64968 --- /dev/null +++ b/apps/dokploy/__test__/db/pool-options.test.ts @@ -0,0 +1,20 @@ +import { describe, expect, it, vi } from "vitest"; + +const postgres = vi.hoisted(() => vi.fn(() => ({}))); + +vi.mock("postgres", () => ({ default: postgres })); +vi.mock("drizzle-orm/postgres-js", () => ({ drizzle: vi.fn(() => ({})) })); +vi.unmock("@dokploy/server/db"); + +describe("@dokploy/server/db", () => { + it("closes connections that sit idle for a minute", async () => { + delete (globalThis as { db?: unknown }).db; + await import("@dokploy/server/db"); + + expect(postgres).toHaveBeenCalledTimes(1); + expect(postgres).toHaveBeenCalledWith( + expect.any(String), + expect.objectContaining({ idle_timeout: 60 }), + ); + }); +}); diff --git a/packages/server/src/db/index.ts b/packages/server/src/db/index.ts index 724cace60e..e666f66a54 100644 --- a/packages/server/src/db/index.ts +++ b/packages/server/src/db/index.ts @@ -17,7 +17,9 @@ const globalForDb = globalThis as unknown as { }; if (!globalForDb.db) { - globalForDb.db = drizzle(postgres(dbUrl), { + // postgres.js keeps every connection it opens for 30-60 minutes. The panel + // is idle most of the time, and each idle backend holds memory in Postgres. + globalForDb.db = drizzle(postgres(dbUrl, { idle_timeout: 60 }), { schema, }); }