Skip to content

[WIP] Fix Prisma connection setup to avoid degraded performance#1409

Closed
Copilot wants to merge 1 commit intomainfrom
copilot/fix-prisma-connection-error
Closed

[WIP] Fix Prisma connection setup to avoid degraded performance#1409
Copilot wants to merge 1 commit intomainfrom
copilot/fix-prisma-connection-error

Conversation

Copy link
Contributor

Copilot AI commented Mar 25, 2026

Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.

Original prompt

Context & Root Cause

The live site at https://adblock-frontend.jayson-knight.workers.dev/ shows "Degraded performance" and "Data may be stale" on every page load, and GET /api/health returns database: { status: "down", latency_ms: 0 }.

The latency_ms: 0 is the key tell: the probe threw before making any network call. The root cause is in worker/lib/prisma.ts:

// CURRENT (broken)
const adapter = new PrismaPg({ connectionString: hyperdriveConnectionString });

@prisma/adapter-pg ≥ 1.0 changed its constructor signature. PrismaPg no longer accepts a plain config object — it requires a pg.Pool instance. Passing { connectionString } causes a synchronous throw at client-creation time, not at query time. Because latency_ms is measured from before createPrismaClient() is called, it records 0 ms. This means every request that touches the database layer silently fails, including anonymous page loads that trigger BetterAuthProvider.verifyToken()createAuth()createPrismaClient().

The Cloudflare Hyperdrive dashboard shows zero connections because the pg.Pool is never created — Prisma throws before it can connect.

The secondary issue — PrismaClientConfigSchema previously only accepted postgresql:// but Hyperdrive's .connectionString property returns postgres://has already been fixed in the current codebase (the schema now accepts both). That fix is documented in docs/troubleshooting/KB-002-hyperdrive-database-down.md. However the PrismaPg Pool constructor bug was introduced at the same time and is still present.


Changes Required

1. Fix worker/lib/prisma.ts — PrismaPg Pool constructor (PRIMARY BUG FIX)

Replace the broken PrismaPg({ connectionString }) call with one that:

  1. Dynamically imports pg (as the rest of the codebase does in worker/utils/pg-pool.ts)
  2. Creates a new Pool({ connectionString }) instance
  3. Passes the Pool instance to PrismaPg
  4. Wraps client creation in a try/catch that surfaces a clear error message instead of a cryptic Prisma internal throw
  5. Calls $disconnect() in a finally block to release the Hyperdrive proxy socket (see existing docs in docs/troubleshooting/neon-troubleshooting.md)

The corrected factory should look like:

export async function createPrismaClient(
    hyperdriveConnectionString: string,
): Promise<InstanceType<typeof PrismaClient>> {
    PrismaClientConfigSchema.parse({ connectionString: hyperdriveConnectionString });
    const moduleName = 'pg';
    const { Pool } = await import(/* @vite-ignore */ moduleName);
    const pool = new Pool({ connectionString: hyperdriveConnectionString });
    const adapter = new PrismaPg(pool);
    return new PrismaClient({ adapter }) as InstanceType<typeof PrismaClient>;
}

If making createPrismaClient async is a larger refactor, an alternative is to keep it synchronous but use the already-existing createPgPool helper from worker/utils/pg-pool.ts. Either approach is acceptable as long as a real pg.Pool is passed to PrismaPg.

Update _internals accordingly and update every call site (health handler, prisma middleware, auth factory) to await the factory.

2. Add a query-level timeout to the database probe in worker/handlers/health.ts

The current databaseProbe() has no timeout on the Prisma query. If the Hyperdrive proxy hangs (e.g. misconfigured binding, cold start), the health check itself will hang until the Worker CPU limit kills the request — which can take 30 seconds and causes the cascading 502 visible in the UI.

Wrap the prisma.$queryRaw call with a Promise.race against AbortSignal.timeout(5000) (5-second deadline). On timeout, return { status: 'down', latency_ms: 5000, error: 'probe timed out' }. This is the same pattern used in worker/handlers/container-status.ts.

Also add an error field to the DatabaseResult type so the error message is surfaced in the JSON response.

3. Add error field propagation in the health response types

Update DatabaseResult in worker/handlers/health.ts:

type DatabaseResult = ServiceResult & {
    db_name?: string;
    hyperdrive_host?: string;
    error?: string;   // NEW — surfaced on down/degraded for UI display
};

Populate error in the catch block with error instanceof Error ? error.message : String(error) (truncated to 200 chars to avoid leaking stack traces).

4. Update worker/middleware/prisma-middleware.ts — add $disconnect in finally

The middleware currently sets the Prisma client in context and calls next() but never disconnects. Add a try/finally around next() to call prisma.$disconnect() after the request completes. This prevents connection leaks under load:

export function prismaMiddleware() {
    return createMiddleware<{ Bindings: Env; Variables: PrismaVariables }>(async (c, next) => {
        if (!c.env.HYPERDRIVE) {
            throw new Err...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

<!-- START COPILOT CODING AGENT TIPS -->
---

📍 Connect Copilot coding agent with [Jira](https://gh.io/cca-jira-docs), [Azure Boards](https://gh.io/cca-azure-boards-docs) or [Linear](https://gh.io/cca-linear-docs) to delegate work to Copilot in one click without leaving your project management tool.

@jaypatrick jaypatrick added bug Something isn't working database Neon Postgre cloudflare Cloudflare Workers / CDN labels Mar 25, 2026
@jaypatrick jaypatrick added this to the beta milestone Mar 25, 2026
@jaypatrick jaypatrick closed this Mar 25, 2026
@github-actions github-actions bot deleted the copilot/fix-prisma-connection-error branch March 25, 2026 23:52
Copilot AI requested a review from jaypatrick March 25, 2026 23:52
Copilot stopped work on behalf of jaypatrick due to an error March 25, 2026 23:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working cloudflare Cloudflare Workers / CDN database Neon Postgre

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants