Das Edge-Problem & die Split-Config
Sobald du einen Datenbank-Adapter (Prisma, Drizzle, …) für Database-Sessions einsetzt, kann deine Middleware kaputtgehen — mit kryptischen Fehlern über fehlende Node-Module. Der Grund: Middleware läuft auf der Edge-Runtime, und viele DB-Treiber tun das nicht. Die Lösung heißt Split-Config.
Die Diagnose in einem Satz: Middleware = Edge-Runtime. DB-Adapter = oft nur Node-Runtime. Lädt deine Middleware die volle
auth.ts mitsamt Adapter, zieht sie damit Node-only-Code in die Edge — und es knallt beim Build oder zur Laufzeit.Warum überhaupt Edge?
- Middleware läuft vor jeder passenden Anfrage, möglichst nah am Nutzer — dafür eine schlanke, schnelle Runtime ohne das volle Node-API.
- Datenbank-Treiber brauchen aber oft genau dieses Node-API (TCP-Sockets,
crypto, native Bindings). - Folge: Der Adapter darf nicht in den Edge-Bundle — die Middleware darf nur den edge-sicheren Teil der Config sehen.
Die Lösung: Config aufteilen
Du trennst die Konfiguration in einen edge-sicheren Kern (Provider + Callbacks, kein Adapter) und die volle Config (Kern + Adapter). Die Middleware nutzt nur den Kern.
auth.config.ts — edge-sicher, kein Adapter
import GitHub from "next-auth/providers/github";
import type { NextAuthConfig } from "next-auth";
export default {
providers: [GitHub],
callbacks: {
authorized({ request, auth }) {
const aufDashboard =
request.nextUrl.pathname.startsWith("/dashboard");
return aufDashboard ? !!auth?.user : true;
},
},
} satisfies NextAuthConfig;auth.ts — volle Config mit Adapter (Node-Runtime)
import NextAuth from "next-auth";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { prisma } from "@/lib/prisma";
import authConfig from "./auth.config";
export const { handlers, signIn, signOut, auth } = NextAuth({
adapter: PrismaAdapter(prisma),
session: { strategy: "jwt" },
...authConfig,
});middleware.ts — nur der edge-sichere Kern
import NextAuth from "next-auth";
import authConfig from "./auth.config";
export const { auth: middleware } = NextAuth(authConfig);
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};Warum eigentlich? — Warum strategy: jwt beim Adapter?
Mit einem DB-Adapter wäre die Default-Session-Strategie
database — jeder Session-Lookup ginge dann gegen die DB. Genau das kann die Edge-Middleware aber nicht. Setzt du session.strategy: "jwt", lebt die Session im signierten Cookie, und die Middleware kann sie ohne DB-Zugriff verifizieren — der Adapter bleibt nur für persistente Daten (User-Tabelle, verknüpfte Accounts) zuständig.Häufiger Denkfehler — Fehler: Module not found (net / dns / fs) in der Middleware
Dieser Fehler ist die Signatur des Edge-Problems: Ein Node-only-Modul (vom DB-Treiber) ist über die volle
auth.ts in den Edge-Bundle gerutscht. Fast immer die Ursache: Die Middleware importiert @/auth statt auth.config. Lass die Middleware nur den edge-sicheren Kern laden, dann verschwindet der Fehler.Tiefer rein — Brauche ich die Split-Config immer?
Nein. Ohne DB-Adapter — also reine JWT-Sessions, Credentials oder nur OAuth ohne Persistenz — funktioniert eine einzige
auth.ts problemlos in der Middleware. Die Aufteilung lohnt sich genau dann, wenn ein nicht-edge-fähiger Adapter ins Spiel kommt. Im Zweifel: erst einfach halten, splitten sobald der erste Edge-Fehler auftaucht.