Open Source
NextAuth / Auth.js Database Schema Explained
Varun Krishnan DEV Community
7 views
The short version
NextAuth (now Auth.js) creates 4 tables in your database: users, accounts, sessions, and verification_tokens. The users and accounts tables have a one-to-one relationship via accounts.user_id. Sessions link to users via sessions.user_id. Verification tokens are short-lived and self-cleaning.
The 4 tables
users
Column
Type
What it means
id
text / UUID
Primary key. Generated by NextAuth.
name
text
Display name from the OAuth provider (Google, GitHub, etc.)
email
text
User's email. May be null if the provider doesn't share it.
email_verified
timestamp
When the email was verified. Null if never verified.
image
text
Profile picture URL from the provider.
created_at
timestamp
When the user first signed in.
updated_at
timestamp
Last profile sync from the provider.
accounts
This table links a user to an OAuth provider. One user can have multiple accounts (e.g., Google + GitHub).
Column
Type
What it means
id
text / UUID
Primary key.
user_id
text
Foreign key → users.id.
type
text
Always "oauth" or "oidc".
provider
text
"google", "github", "discord", etc.
provider_account_id
text
The provider's unique ID for this user.
refresh_token
text
OAuth refresh token (encrypted in production).
access_token
text
OAuth access token (encrypted in production).
expires_at
integer
When the access token expires (Unix timestamp).
token_type
text
Usually "Bearer".
scope
text
Permissions granted by the provider.
id_token
text
OIDC ID token (if using OIDC).
session_state
text
Provider-specific session state.
sessions
Active sessions for each user. NextAuth creates a new row here on every sign-in.
Column
Type
What it means
id
text / UUID
Primary key.
session_token
text
The session token stored in the user's cookie.
user_id
text
Foreign key → users.id.
expires
timestamp
When this session expires.
verification_tokens
Short-lived tokens for email verification, password reset, etc. Self-cleaning old tokens are deleted automatically.
Column
Type
What it means
identifier
text
Email or user ID the token is for.
token
text
The actual token value.
expires
timestamp
When this token expires.
How they connect
users ──1──1── accounts
│
1
│
∞
sessions
users ──1──∞── verification_tokens (via identifier)
One user → one or more accounts (Google, GitHub, etc.)
One user → many sessions (different devices/browsers)
Verification tokens are temporary and don't have a foreign key
What to change
Add a role column to users if you need role-based access control.
Add a phone_number column to users if you're using SMS auth.
Encrypt access_token and refresh_token in production NextAuth doesn't do this by default.
What to leave alone
Don't modify the verification_tokens table it's managed automatically.
Don't change the session_token format it's a signed JWT.
Don't add indexes to provider_account_id unless you're querying it directly (it's already unique).
FAQ
Does NextAuth store passwords?
No. NextAuth is an OAuth-first library. It doesn't handle passwords. If you need email/password auth, use next-auth/providers/credentials with bcrypt, or use a service like Clerk or Lucia.
How do I see what's in my NextAuth tables?
Use dbdiagramr paste your connection string and get a visual schema of your NextAuth tables in seconds.
Can I add custom fields to the users table?
Yes. Add columns to the users table directly. NextAuth will ignore columns it doesn't know about, so you can safely add role, phone_number, preferences, etc.
What happens when a user deletes their account?
NextAuth doesn't cascade deletes by default. You need to manually delete from users, accounts, and sessions. Or add ON DELETE CASCADE to your foreign key constraints.
Is Auth.js the same as NextAuth?
Yes. Auth.js is the rebranded version of NextAuth. The database schema is identical. If you're on NextAuth v4, you're using the same tables.
Read original: https://dev.to/not_varunkv/nextauth-authjs-database-schema-explained-13d2
← Previous
Your system prompt isn't instructions. It's data.
Next →
Help! Trademark Infringement on my [GovernmentName] domain
Related
Filtered should never mean deleted
Open Source
5
DEV Community
Catch Bad Validation Tags at Compile Time with checkerlint
Open Source
5
Dev.to (EN Zone)
Does open source matter if you still depend on someone else’s infrastructure?
Open Source
4
Reddit r/selfhosted
Open, future-proof, multi-room audio
Open Source
4
Reddit r/selfhosted
Comments0
No comments yet — be the first