Using Drizzle ORM
Drizzle ORM is a TypeScript ORM for SQL databases designed with maximum type safety in mind. While Lucia doesn’t provide an adapter for Drizzle itself, it does provide adapters for most database drivers supported by Drizzle.
MySQL#
Make sure to change the table names accordingly. While you can name your Drizzle fields anything you want, the underlying column names must match what’s defined in the docs (e.g user_id
).
// schema.js
import { mysqlTable, bigint, varchar } from "drizzle-orm/mysql-core";
export const user = mysqlTable("auth_user", {
id: varchar("id", {
length: 15 // change this when using custom user ids
}).primaryKey()
// other user attributes
});
export const key = mysqlTable("user_key", {
id: varchar("id", {
length: 255
}).primaryKey(),
userId: varchar("user_id", {
length: 15
})
.notNull()
.references(() => user.id),
hashedPassword: varchar("hashed_password", {
length: 255
})
});
export const session = mysqlTable("user_session", {
id: varchar("id", {
length: 128
}).primaryKey(),
userId: varchar("user_id", {
length: 15
})
.notNull()
.references(() => user.id),
activeExpires: bigint("active_expires", {
mode: "number"
}).notNull(),
idleExpires: bigint("idle_expires", {
mode: "number"
}).notNull()
});
mysql2
#
Install mysql2
and follow the adapter documentation to setup your database.
npm install mysql2
Create a new Pool
from mysql/promise
and use it to initialize both Drizzle and Lucia.
// db.js
import { drizzle } from "drizzle-orm/mysql2";
import { createPool } from "mysql2/promise";
export const pool = mysql.createPool({
// ...
});
export const db = drizzle(pool);
// lucia.ts
import { lucia } from "lucia";
import { mysql2 } from "@lucia-auth/adapter-mysql";
import { pool } from "./db.js";
export const auth = lucia({
adapter: mysql2(pool, tableNames)
});
@planetscale/database
#
Remove all references()
from the schema since Planetscale does not support foreign keys from key
and session
. For example:
export const key = mysqlTable("user_key", {
// ...
userId: varchar("user_id", {
length: 15
}).notNull()
// .references(() => user.id)
// ...
});
Install @planetscale/database
and follow the adapter documentation to setup your database.
npm install @planetscale/database
Create a new connection and use it to initialize both Drizzle and Lucia.
// db.js
import { drizzle } from "drizzle-orm/planetscale-serverless";
import { connect } from "@planetscale/database";
export const connection = connect({
// ...
});
export const db = drizzle(connection);
// lucia.ts
import { lucia } from "lucia";
import { planetscale } from "@lucia-auth/adapter-mysql";
import { connection } from "./db.js";
export const auth = lucia({
adapter: planetscale(connection, tableNames)
});
PostgreSQL#
We recommend using pg
with TCP connections for Supabase and Neon.
Make sure to change the table names accordingly. While you can name your Drizzle fields anything you want, the underlying column names must match what’s defined in the docs (e.g user_id
).
// schema.js
import { pgTable, bigint, varchar } from "drizzle-orm/pg-core";
export const user = pgTable("auth_user", {
id: varchar("id", {
length: 15 // change this when using custom user ids
}).primaryKey()
// other user attributes
});
export const session = pgTable("user_session", {
id: varchar("id", {
length: 128
}).primaryKey(),
userId: varchar("user_id", {
length: 15
})
.notNull()
.references(() => user.id),
activeExpires: bigint("active_expires", {
mode: "number"
}).notNull(),
idleExpires: bigint("idle_expires", {
mode: "number"
}).notNull()
});
export const key = pgTable("user_key", {
id: varchar("id", {
length: 255
}).primaryKey(),
userId: varchar("user_id", {
length: 15
})
.notNull()
.references(() => user.id),
hashedPassword: varchar("hashed_password", {
length: 255
})
});
pg
#
Install pg
and follow the adapter documentation to setup your database.
npm install pg
Create a new Pool
and use it to initialize both Drizzle and Lucia.
// db.js
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
export const pool = new Pool({
// ...
});
export const db = drizzle(pool);
// lucia.ts
import { lucia } from "lucia";
import { pg } from "@lucia-auth/adapter-postgresql";
import { pool } from "./db.js";
export const auth = lucia({
adapter: pg(pool, tableNames)
});
postgres
#
Install postgres
and follow the adapter documentation to setup your database.
npm install postgres
Create a new connection and use it to initialize both Drizzle and Lucia.
// db.js
import { drizzle, PostgresJsDatabase } from "drizzle-orm/postgres-js";
import postgres from "postgres";
export const queryClient = postgres(/* ... */);
export const db: PostgresJsDatabase = drizzle(queryClient);
// lucia.ts
import { lucia } from "lucia";
import { postgres as postgresAdapter } from "@lucia-auth/adapter-postgresql";
import { queryClient } from "./db.js";
export const auth = lucia({
adapter: postgresAdapter(queryClient, tableNames)
});
SQLite#
Make sure to change the table names accordingly. While you can name your Drizzle fields anything you want, the underlying column names must match what’s defined in the docs (e.g user_id
).
// schema.js
import { sqliteTable, text, blob } from "drizzle-orm/sqlite-core";
export const user = sqliteTable("user", {
id: text("id").primaryKey()
// other user attributes
});
export const session = sqliteTable("user_session", {
id: text("id").primaryKey(),
userId: text("user_id")
.notNull()
.references(() => user.id),
activeExpires: blob("active_expires", {
mode: "bigint"
}).notNull(),
idleExpires: blob("idle_expires", {
mode: "bigint"
}).notNull()
});
export const key = sqliteTable("user_key", {
id: text("id").primaryKey(),
userId: text("user_id")
.notNull()
.references(() => user.id),
hashedPassword: text("hashed_password")
});
better-sqlite3
#
Install better-sqlite3
and follow the adapter documentation to setup your database.
npm install better-sqlite3
Create a new Database
and use it to initialize both Drizzle and Lucia.
// db.js
import { drizzle, BetterSQLite3Database } from "drizzle-orm/better-sqlite3";
import sqlite from "better-sqlite3";
export const sqliteDatabase = sqlite(/* ... */);
export const db: BetterSQLite3Database = drizzle(sqliteDatabase);
// lucia.ts
import { lucia } from "lucia";
import { betterSqlite3 } from "@lucia-auth/adapter-sqlite";
import { sqliteDatabase } from "./db.js";
export const auth = lucia({
adapter: betterSqlite3(sqliteDatabase, tableNames)
});
Cloudflare D1#
Follow the adapter documentation to setup your database.
import { drizzle } from "drizzle-orm/d1";
const initializeDrizzle = (db: D1Database) => {
return drizzle(db);
};
const initializeLucia = (db: D1Database) => {
const auth = lucia({
adapter: d1(db, tableNames)
// ...
});
return auth;
};
libSQL (Turso)#
Install @libsql/client
and follow the adapter documentation to setup your database.
npm install @libsql/client
Create a new client and use it to initialize both Drizzle and Lucia.
// db.js
import { drizzle } from "drizzle-orm/libsql";
import { createClient } from "@libsql/client";
export const libsqlClient = createClient({
// ...
});
export const db = drizzle(libsqlClient);
// lucia.ts
import { lucia } from "lucia";
import { libsql } from "@lucia-auth/adapter-sqlite";
import { libsqlClient } from "./db.js";
export const auth = lucia({
adapter: libsql(libsqlClient, tableNames)
});