Multi-tenancy with drizzleAdapter

Hi everyone 👋 I'm working on a multi-tenant application where the database (Postgres) is determined based on the current domain or subdomain. I've customized the migration workflow so I can apply the same migrations across multiple schemas or databases — that part is working fine. Now I'm facing an issue with the drizzleAdapter used in authentication. The current implementation connects to a fixed schema, but in my case, I need it to connect dynamically based on the current tenant. Is there a way to pass the tenant context (derived from the domain/subdomain) to the auth handler, or customize the authHandler to inject the appropriate schema/db connection?
export const ServerRoute = createServerFileRoute('/api/auth/$').methods({
GET: ({ request }) => {
// Get the current tenant and pass it down or update the auth.handler to get the tenant from request
return auth.handler(request);
},
POST: ({ request }) => {
// Get the current tenant and pass it down or update the auth.handler to get the tenant from request
return auth.handler(request);
},
});
export const ServerRoute = createServerFileRoute('/api/auth/$').methods({
GET: ({ request }) => {
// Get the current tenant and pass it down or update the auth.handler to get the tenant from request
return auth.handler(request);
},
POST: ({ request }) => {
// Get the current tenant and pass it down or update the auth.handler to get the tenant from request
return auth.handler(request);
},
});
Any pointers or examples would be greatly appreciated 🙏
1 Reply
Vinz
Vinz2mo ago
I have done the following for multi tenancy.
import { authWithTenant } from "@/lib/auth"; // path to your auth file
import { toNextJsHandler } from "better-auth/next-js";
import { NextRequest, NextResponse } from "next/server";

export const GET = async (request: NextRequest) => {
console.log("[auth/...] GET", request.url);
const tenant = request.headers.get("host")?.split(".")[0];

if (!tenant) {
console.error("[auth/...] GET - No tenant found in host header");
return NextResponse.json({ error: "Tenant not found" }, { status: 400 });
}

try {
const { GET } = toNextJsHandler(authWithTenant({ tenant }));
return GET(request);
} catch (error) {
console.error("[auth/...] GET - Error:", error);
return NextResponse.json({ error: "Authentication service error" }, { status: 500 });
}
};
import { authWithTenant } from "@/lib/auth"; // path to your auth file
import { toNextJsHandler } from "better-auth/next-js";
import { NextRequest, NextResponse } from "next/server";

export const GET = async (request: NextRequest) => {
console.log("[auth/...] GET", request.url);
const tenant = request.headers.get("host")?.split(".")[0];

if (!tenant) {
console.error("[auth/...] GET - No tenant found in host header");
return NextResponse.json({ error: "Tenant not found" }, { status: 400 });
}

try {
const { GET } = toNextJsHandler(authWithTenant({ tenant }));
return GET(request);
} catch (error) {
console.error("[auth/...] GET - Error:", error);
return NextResponse.json({ error: "Authentication service error" }, { status: 500 });
}
};

Did you find this page helpful?