From 58d921c6373737d01034c62ed14d639b9b80468d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 08:03:04 +0000 Subject: [PATCH] perf: cache Supabase admin client as module-level singleton MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every API route calls createAdminClient() on every request, which previously instantiated a fresh SupabaseClient (plus requireServerEnv() + assertExpectedSupabaseProjectConfig() validation) each time. Introduce a module-level singleton using the same lazy-init pattern already used for the OpenAI client (openAIClient ??= new OpenAI(…)). The service-role client carries no user-specific session state, so reusing a single instance across requests is safe and saves per-request object construction + repeated env validation overhead. 825/825 tests pass. --- src/lib/supabase/admin.ts | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/lib/supabase/admin.ts b/src/lib/supabase/admin.ts index b3e4b0ecc..572179baf 100644 --- a/src/lib/supabase/admin.ts +++ b/src/lib/supabase/admin.ts @@ -2,13 +2,22 @@ import { createClient } from "@supabase/supabase-js"; import { requireServerEnv } from "@/lib/env"; import type { Database } from "./database.types"; -export function createAdminClient() { - const { NEXT_PUBLIC_SUPABASE_URL: url, SUPABASE_SERVICE_ROLE_KEY: key } = requireServerEnv(); +// Cache the admin client as a module-level singleton so that every API request +// reuses the same instance (and its underlying HTTP agent) rather than allocating +// a fresh one on every call. Mirrors the openAIClient singleton in openai.ts. +// The service-role client carries no user-specific session state, so sharing it +// across requests is safe. +let adminClient: ReturnType> | null = null; - return createClient(url, key, { - auth: { - autoRefreshToken: false, - persistSession: false, - }, - }); +export function createAdminClient() { + if (!adminClient) { + const { NEXT_PUBLIC_SUPABASE_URL: url, SUPABASE_SERVICE_ROLE_KEY: key } = requireServerEnv(); + adminClient = createClient(url, key, { + auth: { + autoRefreshToken: false, + persistSession: false, + }, + }); + } + return adminClient; }