A common pattern for generated API clients (oazapfts, openapi-typescript-fetch, etc.) in SvelteKit is a module-level defaults object, configured per-request in hooks.server.ts:
export const handleSDK: Handle = async ({ event, resolve }) => {
sdk_defaults.headers.cookie = event.request.headers.get('cookie'); // RACE
sdk_defaults.fetch = wrap(fetch, event.route, event.url); // RACE
return resolve(event);
};This works in dev and low traffic, but the singleton is shared across all in-flight requests in the Node process. Loads await between the mutation and the SDK calls, so concurrent request B overwrites the cookie header while request A's loads are still running — request A's API calls carry request B's cookies. This is a cross-user data leak, not just a correctness bug, and it's silent.
Don't count on SvelteKit's own cookie forwarding to save you either: event.fetch only auto-forwards cookies cross-origin when the target hostname equals the app hostname or is a subdomain of it (runtime/server/fetch.js, the .${url.hostname}.endsWith(...) check). Sibling domains (api-dev.example.dev vs app-dev.example.dev) and docker-internal hostnames (http://api:8081) get nothing.
Correct setups, in order of preference:
Per-call opts + handleFetch. Every oazapfts function accepts trailing
opts?: RequestOptswithfetch/headers/baseUrloverrides. Pass{ fetch: event.fetch }from loads; add ahandleFetchhook that injects the raw incomingCookieheader (and rewrites public→internal API URL) for API-bound requests only. Per-request state lives on the event, nothing shared.Request-scoped default fetch. Set
defaults.fetchONCE at server startup to a wrapper that resolves the current event:getRequestEvent()from$app/server(kit ≥ 2.20), or below that a self-rolledAsyncLocalStorage<RequestEvent>whose.run(event, () => resolve(event))wraps the first handle in the sequence. The wrapper delegates toevent.fetchwhen in a request, plainfetchotherwise. This makes bare SDK calls in endpoints/hooks per-request-correct with zero callsite churn (ALS context survives awaits on Node ≥ 20 / adapter-node).
Either way, delete every per-request write to the singleton; baseUrl/credentials can be set once at module scope.