← All schemas
Schema Library

NextAuth.js Database Schema

NextAuth.js (now Auth.js) persists users, OAuth accounts, sessions, and email verification tokens in four tables: users, accounts, sessions, and verification_token. This diagram follows the PostgreSQL adapter's SQL: accounts and sessions have their own id, and both carry a userId that points at users.id. A single user can have many accounts (one per OAuth provider) and many sessions.

Written by Varun Krishnan · Founder, dbdiagramr

Published · Updated

Source: @auth/pg-adapter v1.11.3 schema.sql (next-auth, released 2026-07-20) · License: ISC

Tables
4
Core table
users
Relationship
User 1→N Account
Adapter
1.11.3

PostgreSQL adapter schema from @auth/pg-adapter v1.11.3, released 2026-07-20.

The adapter schema declares no foreign-key constraints and omits Prisma-only models and indexes. adapter schema.sql.

NextAuth.js database schema diagram showing every table, column, and foreign key

Scroll horizontally to see the full diagram. Click it to open at full size.

Open in DBdiagramr to edit →

Embed this diagram

Paste this HTML into a README, docs page, or blog post. The image links back to the full schema page.

<a href="https://www.dbdiagramr.space/schema/nextauth">
  <img src="https://www.dbdiagramr.space/schemas/nextauth-er-diagram.svg" alt="NextAuth.js Database Schema (Auth.js)" width="922" height="712" />
</a>
<p><a href="https://www.dbdiagramr.space/schema/nextauth">NextAuth.js Database Schema (Auth.js)</a> by dbdiagramr</p>

Tables in the NextAuth.js schema

ColumnTypeNullableKey
users
idintegerNoPK
namevarchar(255)Yes-
emailvarchar(255)Yes-
emailVerifiedtimestamptzYes-
imagetextYes-
accounts
idintegerNoPK
userIdintegerNoFK → users.id
typevarchar(255)No-
providervarchar(255)No-
providerAccountIdvarchar(255)No-
refresh_tokentextYes-
access_tokentextYes-
expires_atbigintYes-
id_tokentextYes-
scopetextYes-
session_statetextYes-
token_typetextYes-
sessions
idintegerNoPK
userIdintegerNoFK → users.id
expirestimestamptzNo-
sessionTokenvarchar(255)No-
verification_token
identifiertextNoPK
tokentextNoPK
expirestimestamptzNo-

Table relationships

2 relationships connect the tables in this schema. Each entry shows the child columns, the parent columns they reference, and the cardinality.

These are the userId joins the PostgreSQL adapter uses. Its SQL does not declare foreign-key constraints; the Prisma adapter's PostgreSQL schema does, with ON DELETE CASCADE for accounts and sessions.

One-to-many

accounts.userId → users.id

One user can have many accounts (accounts.userId -> users.id, required).

One-to-many

sessions.userId → users.id

One user can have many sessions (sessions.userId -> users.id, required).

Common queries

These PostgreSQL queries run against the schema shown on this page.

Active database sessions

List unexpired sessions and the user they belong to.

select u.email, s.id, s."sessionToken", s.expires
from sessions s
join users u on u.id = s."userId"
where s.expires > now()
order by s.expires;

Accounts by provider

Show every provider linked to each user.

select u.email, a.provider, a."providerAccountId"
from accounts a
join users u on u.id = a."userId"
order by u.email, a.provider;

Users without an OAuth account

Find users that have no row in accounts.

select u.id, u.email
from users u
left join accounts a on a."userId" = u.id
where a.id is null;

Sessions expiring soon

Sessions due to expire in the next 30 days.

select u.email, s.id, s.expires
from sessions s
join users u on u.id = s."userId"
where s.expires between now() and now() + interval '30 days'
order by s.expires;

What each NextAuth table stores

The four tables have separate jobs. The adapter expects these names and columns; the values come from the provider or from Auth.js itself.

TableWhat it stores
usersOne row per person: id, display name, email, verification timestamp, and profile image. A user can own several accounts and sessions.
accountsOne row per provider link: the provider name, the provider's account id, OAuth tokens, and the owning userId. A user with Google and GitHub has two rows.
sessionsOne row per database session: the session token, the owning userId, and the expiry time. Use this table only with the database session strategy.
verification_tokenShort-lived tokens for email magic-link sign-in. The identifier and token form the primary key; rows are single-use and expire after one day by default.

Exact verification table name: the @auth/pg-adapter SQL creates verification_token (singular). Prisma's PostgreSQL model is named VerificationToken and creates a quoted "VerificationToken" table by default. verification_tokens exists only if you add a @@map yourself, so this page uses the adapter's singular name.

The PostgreSQL adapter's SQL does not declare foreign-key constraints. The relationships shown in the diagram are the userId joins the adapter uses. The Prisma adapter's PostgreSQL schema does declare them and adds onDelete: Cascade for accounts and sessions.

Custom fields, passwords, and account deletion

Custom fields. Auth.js models can be extended with additional fields. Add columns to the relevant table and populate them in your own application code; the adapter still manages the fields it defines. A common example is a role column on users.

Passwords. The Credentials provider does not persist data in the database by default. If you use it, your own code stores the user and hashes the password, for example with bcrypt or argon2. Auth.js is not a password manager.

Account deletion. With the Prisma adapter's PostgreSQL schema, Account.user and Session.user use onDelete: Cascade, so a database-enforced user delete removes the linked rows. With the PostgreSQL adapter's SQL, there are no foreign keys, so deletes do not cascade; remove accounts and sessions in the same transaction or add your own constraints. Do not assume one adapter's behavior applies to the other.

Read the Auth.js database models and the Credentials provider docs for the source wording.

Frequently asked questions

Related schema diagrams

Visualize your own database

Paste your PostgreSQL connection string and get an interactive ER diagram of your own schema in under 10 seconds. No signup required.

Try it free →