D1 adapter: `D1SqliteAdapter` inherits `supportsMultipleConnections = false`, so kysely serializes every query behind a mutex shared across requests on a Workers isolate
@better-auth/kysely-adapter (1.7.5, still present in 1.7.6) defines class D1SqliteAdapter extends SqliteAdapter {}, so kysely builds a ConnectionMutex. When the auth instance is memoized per isolate (the usual pattern on Workers), one request awaits a promise created by another. Once V8 optimizes the waiting code, the waiter can resume outside its own I/O context, and its next D1 call throws Cannot perform I/O on behalf of a different request (I/O type: SpanParent).
D1 keeps no connection state (each query is a fresh prepared statement on the binding), and the driver already refuses interactive transactions, so the mutex protects nothing.
Fix: override get supportsMultipleConnections() { return true; } on D1SqliteAdapter:
-var D1SqliteAdapter = class extends SqliteAdapter {};
+var D1SqliteAdapter = class extends SqliteAdapter {
+ get supportsMultipleConnections() {
+ return true;
+ }
+};We've run this as a local patch in production, with a concurrency test that drives parallel requests through one memoized auth instance.
Source: better-auth/better-auth