fix: cap Prisma pool during next build to stop deploy SSG timeouts
Deploy / release (push) Skipped
Deploy / deploy (push) Successful in 1m28s

Next build workers were each opening up to DATABASE_POOL_SIZE connections and exhausting MySQL (pool active=0), hanging sitemap generation. Cap build pool to 5, fail connect faster, limit SSG concurrency, and make sitemap dynamic.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-07-21 21:28:27 +02:00
1 parent 803e8f36c1
commit 77931db775
5 files changed
+53 -3

No files matched your search

+19
View File
@@ -0,0 +1,19 @@
import { describe, expect, it } from "vitest";
import { resolvePrismaConnectionLimit } from "./prisma-pool";
describe("resolvePrismaConnectionLimit", () => {
it("caps the pool during production build phases", () => {
expect(resolvePrismaConnectionLimit(40, "phase-production-build")).toBe(5);
expect(
resolvePrismaConnectionLimit(40, "phase-production-compile"),
).toBe(5);
expect(resolvePrismaConnectionLimit(3, "phase-production-build")).toBe(3);
});
it("keeps the configured pool outside build", () => {
expect(resolvePrismaConnectionLimit(40, undefined)).toBe(40);
expect(resolvePrismaConnectionLimit(40, "phase-development-server")).toBe(
40,
);
});
});
+16
View File
@@ -0,0 +1,16 @@
/**
* Cap pool size during `next build` so N workers × pool don't exhaust MySQL.
* Kept free of Prisma/env imports so unit tests can exercise it in isolation.
*/
export function resolvePrismaConnectionLimit(
poolSize: number,
phase = process.env.NEXT_PHASE,
): number {
if (
phase === "phase-production-build" ||
phase === "phase-production-compile"
) {
return Math.min(poolSize, 5);
}
return poolSize;
}
+12 -3
View File
@@ -1,20 +1,29 @@
import { PrismaMariaDb } from "@prisma/adapter-mariadb";
import { env } from "@/env";
import { PrismaClient } from "@/generated/prisma/client";
import { resolvePrismaConnectionLimit } from "@/lib/prisma-pool";
const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };
function createPrismaClient(): PrismaClient {
const url = new URL(env.DATABASE_URL);
const isBuild =
process.env.NEXT_PHASE === "phase-production-build" ||
process.env.NEXT_PHASE === "phase-production-compile";
const connectionLimit = resolvePrismaConnectionLimit(env.DATABASE_POOL_SIZE);
// Fail fast during SSG so Next can retry/fallback instead of hanging 30s+.
const connectTimeout = isBuild
? Math.min(env.DATABASE_CONNECT_TIMEOUT_MS, 5_000)
: env.DATABASE_CONNECT_TIMEOUT_MS;
const adapter = new PrismaMariaDb({
host: url.hostname,
port: Number(url.port) || 3306,
user: decodeURIComponent(url.username),
password: decodeURIComponent(url.password),
database: url.pathname.replace(/^\//, ""),
connectionLimit: env.DATABASE_POOL_SIZE,
connectTimeout: env.DATABASE_CONNECT_TIMEOUT_MS,
acquireTimeout: env.DATABASE_CONNECT_TIMEOUT_MS,
connectionLimit,
connectTimeout,
acquireTimeout: connectTimeout,
idleTimeout: env.DATABASE_IDLE_TIMEOUT_MS,
});
return new PrismaClient({