Lucia
Minimal session management primitives — you control the auth logic
Overview
Lucia is a minimal, framework-agnostic session management library. It deliberately does NOT handle password hashing, OAuth flows, or token generation — it only manages sessions and their lifecycle. You write the auth logic; Lucia handles the session store.
The Lucia author (pilcrowOnPaper) has since sunset active development and now recommends reading the Lucia source as educational material and writing session management yourself. However, the existing library remains stable and production-worthy.
For greenfield projects, the author's newer library oslo provides cryptographic primitives (PKCE, HMAC, password hashing) that you assemble yourself — the "build your own auth" approach with solid primitives.
Architecture fit
Best suited to run inside your main application process alongside your app logic and database.
Key features
Trade-offs
Complete control — you write every auth decision
More code to write — no OAuth or password handling built in
Tiny footprint, no magic, easy to audit
Actively sunset by author — consider it in maintenance mode
Best for learning how auth works under the hood
No organizations, 2FA, or passkeys without building them
Works everywhere Node.js runs
Smaller plugin/community ecosystem than Auth.js or Better Auth
✓ When to use
- →You want to deeply understand session management
- →Custom auth flows that no framework handles well
- →SvelteKit or Astro apps where Auth.js support is limited
- →Teams who value simplicity over features
✗ When NOT to use
- →Production apps starting today — Better Auth covers the same ground with more features
- →Need OAuth, 2FA, or passkeys without writing them yourself
- →Large teams who need a maintained, feature-rich solution
Implementation
TypeScript// lib/lucia.ts
import { Lucia } from "lucia";
import { PrismaAdapter } from "@lucia-auth/adapter-prisma";
export const lucia = new Lucia(new PrismaAdapter(prisma.session, prisma.user), {
sessionCookie: { attributes: { secure: process.env.NODE_ENV === "production" } },
getUserAttributes: (attrs) => ({ email: attrs.email, username: attrs.username }),
});
// Register — hash password yourself (use oslo/password)
import { Argon2id } from "oslo/password";
const hash = await new Argon2id().hash(password);
await prisma.user.create({ data: { email, passwordHash: hash } });
const session = await lucia.createSession(user.id, {});
const cookie = lucia.createSessionCookie(session.id);
// Middleware — validate session on every request
const sessionId = lucia.readSessionCookie(req.headers.get("cookie") ?? "");
if (!sessionId) return new Response(null, { status: 401 });
const { session, user } = await lucia.validateSession(sessionId);
if (!session) return new Response(null, { status: 401 });
// Rolling session — extend expiry on activity
if (session.fresh) {
res.headers.set("Set-Cookie", lucia.createSessionCookie(session.id).serialize());
}In production
Popular in SvelteKit and Astro communities for custom auth setups
Widely used in auth tutorials for teaching session management fundamentals
Other frameworks
Better Auth
TypeScript-first, self-hosted authentication with full schema ownership
Auth.js (NextAuth v5)
The most popular authentication library for Next.js and the JS ecosystem
Clerk
Managed authentication with prebuilt UI components — zero infrastructure
Passport.js
The original Node.js authentication middleware — 500+ strategies