You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cloudflare Workers中Better Auth与Supabase连接问题排查

在Cloudflare Workers中连接Better Auth与Supabase PostgreSQL的问题

背景

  • 运行环境:Cloudflare Workers
  • 数据库:Supabase(带事务池的PostgreSQL)
  • 测试的ORM/客户端:postgres.js、kysely
  • 认证库:Better Auth

问题

  • 使用Supabase事务池(pgBouncer)→ 间歇性可用(约50%失败率)
  • 使用postgres.js或kysely→ 在Cloudflare Workers中经常被阻断
  • 问题疑似与Workers的TCP连接限制相关

尝试的解决方案

尝试方案1:使用PgPool

PgPool连接配置

import { Pool } from "pg";
import "dotenv/config";

const connectionString = process.env.DATABASE_URL;
if (!connectionString) {
    throw new Error ("❌ 数据库URL未定义,请检查.env文件。")
}

export const database  = new Pool ({
     connectionString,
     max: 10,
     //ssl: { rejectUnauthorized: false }
 });

搭配PgPool的Better Auth配置

import { betterAuth } from "better-auth";
import {database} from "./db.connect.ts";
import "dotenv/config";

export const auth = betterAuth({

  // database: database,
  
  secret: process.env.BETTER_AUTH_SECRET,
  
  trustedOrigins: [
      process.env.BETTER_AUTH_URL!,
  ],
// 其余配置

});

✅ 偶尔可用
❌ 随机失败(约每2次请求失败1次)

尝试方案2:直接适配器(无异步)

Kysely连接配置

import { Kysely } from "kysely";
import { PostgresJSDialect } from "kysely-postgres-js";
import postgres from "postgres";

const connectionString = process.env.DATABASE_URL!;

export const kysely = new Kysely<any>({
    dialect: new PostgresJSDialect({
        postgres: postgres(connectionString)
    }),
});

搭配Kysely的Better Auth配置

import { betterAuth } from "better-auth";
import {kysely} from "./kysely.ts";
import { kyselyAdapter } from "@better-auth/kysely-adapter";


import "dotenv/config";

export const auth = betterAuth({

 database: kyselyAdapter (kysely),
  
  secret: process.env.BETTER_AUTH_SECRET,
  
  trustedOrigins: [
      process.env.BETTER_AUTH_URL!,
  ],
// 其余配置

});

从第二次请求开始,Wrangler返回错误:

Error: Cannot perform I/O on behalf of a different request. I/O objects (such as streams, request/response bodies, and others) created in the context of one request handler cannot be accessed from a different request's handler. This is a limitation of Cloudflare Workers which allows us to improve overall performance. (I/O type: Writable)

尝试方案3:动态适配器

Kysely连接配置

import { Kysely } from "kysely";
import { PostgresJSDialect } from "kysely-postgres-js";
import postgres from "postgres";

const connectionString = process.env.DATABASE_URL!;

export function createKysely () {
    return new Kysely<any>({
        dialect: new PostgresJSDialect({
            postgres: postgres(connectionString)
        }),
    });
}

搭配Kysely的Better Auth配置

import { betterAuth } from "better-auth";
import {createKysely} from "./kysely.ts";
import { kyselyAdapter } from "@better-auth/kysely-adapter";


import "dotenv/config";

export const auth = betterAuth({

 database : kyselyAdapter (createKysely())
  
  secret: process.env.BETTER_AUTH_SECRET,
  
  trustedOrigins: [
      process.env.BETTER_AUTH_URL!,
  ],
// 其余配置

});

我还尝试了:

database: {async get() {
    return kyselyAdapter (createKysely()) 
    }
  },

仍返回相同错误。

猜想

Cloudflare Workers可能:

  • 无法妥善支持原生TCP连接
  • 无法可靠支持连接池(pg/pgBouncer)
  • 需要基于HTTP的数据库驱动

核心问题

  1. Cloudflare Workers是否支持TCP方式的postgres.js/Kysely?
  2. Supabase pgBouncer能否在边缘无服务器环境可靠运行?
  3. Workers中Better Auth搭配Supabase的推荐架构是什么?

是否应选择:

  • 使用Supabase HTTP API而非直接数据库访问?
  • 添加Node.js后端作为代理?
  • 切换至Neon HTTP驱动等无服务器Postgres驱动?

解答

1. Cloudflare Workers对TCP方式postgres.js/Kysely的支持

Cloudflare Workers有限支持原生TCP连接,但存在严格限制:

  • Workers的运行环境是无状态边缘容器,每个请求的执行上下文完全隔离,跨请求复用TCP连接会触发「跨请求I/O访问」错误。
  • postgres.js和Kysely默认的TCP驱动依赖长连接,而Workers的连接数配额极低,且连接会在请求结束后被强制回收,导致连接池失效、请求频繁失败。

2. Supabase pgBouncer在边缘环境的可靠性

Supabase的pgBouncer事务池不适合直接在Cloudflare Workers中使用:

  • pgBouncer依赖长连接复用,但Workers的短生命周期和上下文隔离特性会频繁断开连接,导致连接池命中率极低,出现你看到的50%失败率。
  • 边缘环境与Supabase集群的网络延迟波动,会进一步加剧连接不稳定问题。

3. Workers中Better Auth搭配Supabase的推荐架构

优先方案:使用Supabase HTTP API替代直接数据库访问

直接通过Supabase提供的REST/GraphQL API操作数据库,完全适配Workers的边缘环境:

  • 无需维护TCP连接,所有请求通过HTTP完成,规避Workers的I/O限制。
  • Better Auth可以通过自定义适配器,调用Supabase API完成用户数据的读写操作。

示例简化配置思路:

import { betterAuth } from "better-auth";
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE_KEY!);

export const auth = betterAuth({
  database: {
    // 实现Better Auth所需的数据库操作方法,内部调用Supabase API
    async createUser(user) {
      const { data, error } = await supabase.from('users').insert(user).select().single();
      if (error) throw error;
      return data;
    },
    // 其他必要方法(getUser, updateUser等)
  },
  secret: process.env.BETTER_AUTH_SECRET,
  trustedOrigins: [process.env.BETTER_AUTH_URL!],
  // 其余配置
});

备选方案:使用基于HTTP的Postgres驱动

如果一定要直接操作数据库,替换为支持HTTP协议的Postgres驱动(如Neon的@neondatabase/serverless):

  • 该驱动通过HTTP/HTTPS发送SQL请求,完全兼容Workers的环境,无需TCP连接。
  • 适配Kysely的话,使用@neondatabase/serverless作为dialect:
import { Kysely } from "kysely";
import { NeonDialect } from "kysely-neon";
import { neon } from '@neondatabase/serverless';

const connectionString = process.env.DATABASE_URL!;

export const kysely = new Kysely<any>({
  dialect: new NeonDialect({
    pool: {
      connectionString,
    },
  }),
});

然后将此Kysely实例传入Better Auth的适配器即可,注意要确保驱动版本与Better Auth适配器兼容。

不推荐方案:添加Node.js后端代理

这种方式会增加架构复杂度和延迟,违背使用Cloudflare Workers的边缘优势,除非有特殊业务需求,否则不建议采用。


内容的提问来源于stack exchange,提问作者Nazim M.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 16:47:26