Skip to main content
theAuth uses Drizzle ORM under the hood. You pick a provider and pass the connection URL; theAuth handles the rest.

Choosing a provider

Setup

The sqlite provider uses sql.js (SQLite compiled to WebAssembly), which ships with @glinr/theauth. It needs no native build and runs on Node.js, Bun, Deno, and edge runtimes.
For in-memory SQLite (tests and CI), use :memory: as the URL:
sql.js keeps the database in memory. For a file path, theAuth loads the file at startup if it exists and rewrites the whole file after each write statement. That is fine for development and small apps, but it is a single-process setup: do not point several processes at the same file. theAuth turns on foreign keys (PRAGMA foreign_keys = ON). It does not enable WAL mode for this provider.

Auto-migration

By default, theAuth calls CREATE TABLE IF NOT EXISTS at startup for the tables your config needs. This is safe to run on every start, but it only creates missing tables, it does not alter existing ones. There is no manual migration step for a new project. Tables are created per feature, so a small config gives you a small schema. Users and the secondary storage table are always created. Everything else depends on the config: If you add a feature later, restart once and the new tables appear. Add agents: { enabled: true } if you use agents, since agent tables are not created without it. The @glinr/theauth-email plugin creates its own theauth_email_accounts table. To disable this (e.g. when you manage migrations externally with Flyway, Liquibase, or drizzle-kit push), set skipMigrations: true:
When skipMigrations: true, you are responsible for keeping the schema in sync. theAuth will fail at runtime if expected tables or columns are missing.

Schema overview

The full set of tables theAuth can create is below. Which ones exist in your database depends on your config, see above. All table and column names use snake_case. IDs are text. In the SQLite schema, timestamps are stored as integers.

Peer dependencies

theAuth uses dynamic imports for the SQLite, Postgres, and MySQL drivers so they remain optional. You will get a clear error message at startup if the required package is missing, for example:

Testing with in-memory SQLite

Use :memory: for fast, isolated tests that need no setup or teardown:
Each createTheAuth() call with :memory: gets a completely isolated database, so tests never share state.

Prisma adapter

Read theAuth tables through an existing PrismaClient.

Configuration

Full createTheAuth() options including database and secrets.

Test utilities

In-memory mock server and factories for auth-dependent tests.

Terraform

Provision agents and permissions as infrastructure-as-code.
Last modified on October 7, 2026