Faster Page Navigation: Eliminating the Per-Request DB Lookup in Middleware
Faster Page Navigation: Eliminating the Per-Request DB Lookup in Middleware
Release: v0.1.83 · Performance · PERF-13
Background
Every protected route in the application passes through a central middleware layer (src/middleware.ts). This middleware calls auth() from NextAuth to verify that the user is authenticated before allowing the request to proceed.
While authentication checks are necessary, the way NextAuth resolves a session has a significant impact on performance. When configured to use database sessions, the Drizzle ORM adapter performs a live database lookup on every single call to auth() — meaning every page navigation, every API call, every server-side render for an authenticated user incurs a DB round-trip before any application logic even runs.
For a compliance platform where users routinely navigate between screening results, entity profiles, and monitoring dashboards, this overhead compounds quickly.
The Fix
The solution is to ensure NextAuth uses JWT sessions instead of database sessions.
// auth.ts (NextAuth configuration)
export const { auth, handlers, signIn, signOut } = NextAuth({
// ...
session: {
strategy: 'jwt', // ✅ Session resolved from signed token — no DB call
},
// ...
});
With strategy: 'jwt', the session is encoded in a signed, server-verified token stored in a cookie. When auth() is called in middleware, NextAuth decodes and verifies the token locally — no database, no network call, no Drizzle adapter involved. The session is available in microseconds rather than milliseconds.
Why This Matters for Middleware Specifically
Middleware in Next.js runs on the Edge Runtime, which sits in front of every request. Any latency introduced here is paid before the page or API handler even begins executing. A single unnecessary DB round-trip in middleware effectively adds that latency to 100% of authenticated traffic.
| Session Strategy | Middleware DB Call | Typical Added Latency |
|---|---|---|
database (Drizzle adapter) | ✅ Yes, on every request | ~10–50ms per navigation |
jwt | ❌ None | Negligible (local crypto) |
If Database Sessions Are Required
Some deployments require database sessions — for example, to support immediate session revocation without waiting for a token to expire. In that case, the recommendation is to introduce an Edge-compatible session cache (such as a Redis or KV store accessible from the Edge Runtime) so that session lookups can be served from cache rather than hitting the primary database on every request.
A cache with a short TTL (e.g. 30–60 seconds) dramatically reduces DB load while keeping revocation windows acceptably short.
Affected File
src/middleware.ts
No Breaking Changes
This change is internal to the session resolution mechanism. The session object shape, authentication behaviour, and all public-facing routes remain unchanged.