MongoDB
Run payload-better-auth on Payload's MongoDB adapter. The adapter detects MongoDB itself; three settings change from the Postgres setup.
The adapter detects MongoDB from Payload's database adapter and configures itself, so payloadAdapter() needs no extra options. IDs are always text (ObjectId strings) on MongoDB.
Differences from Postgres
| Postgres (default) | MongoDB | |
|---|---|---|
| ID type | 'number' (SERIAL) | 'text' (ObjectId strings) |
advanced.database.generateId | Set to 'serial' | Do not set |
betterAuthStrategy() | Default | idType: 'text' |
Payload config
Install the MongoDB adapter instead of the Postgres adapter:
npm i @payloadcms/db-mongodbKeep the secrets and app origin from Installation, and replace DATABASE_URL with:
DATABASE_URI=mongodb://127.0.0.1:27017/my-appimport { buildConfig } from 'payload'
import { mongooseAdapter } from '@payloadcms/db-mongodb'
import { betterAuth } from 'better-auth'
import {
betterAuthCollections,
createBetterAuthPlugin,
payloadAdapter,
} from '@delmaredigital/payload-better-auth'
import { betterAuthOptions } from './lib/auth/config'
import { Users } from './collections/Users'
import { getBaseUrl } from './lib/auth/getBaseUrl'
const baseUrl = getBaseUrl()
export default buildConfig({
secret: process.env.PAYLOAD_SECRET!,
collections: [Users],
plugins: [
betterAuthCollections({ betterAuthOptions, skipCollections: ['user'] }),
createBetterAuthPlugin({
createAuth: (payload) =>
betterAuth({
...betterAuthOptions,
database: payloadAdapter({ payloadClient: payload }),
// Do NOT set advanced.database.generateId
secret: process.env.BETTER_AUTH_SECRET,
baseURL: baseUrl,
trustedOrigins: [baseUrl],
}),
}),
],
db: mongooseAdapter({ url: process.env.DATABASE_URI! }),
})Users collection and session helpers
import type { CollectionConfig } from 'payload'
import { betterAuthStrategy } from '@delmaredigital/payload-better-auth'
export const Users: CollectionConfig = {
slug: 'users',
auth: {
disableLocalStrategy: true,
strategies: [betterAuthStrategy({ idType: 'text' })],
},
access: {
read: ({ req }) => {
if (!req.user) return false
if (req.user.role === 'admin') return true
return { id: { equals: req.user.id } }
},
admin: ({ req }) => req.user?.role === 'admin',
},
fields: [
{ name: 'email', type: 'email', required: true, unique: true },
{ name: 'emailVerified', type: 'checkbox', defaultValue: false },
{ name: 'name', type: 'text' },
{ name: 'image', type: 'text' },
{
name: 'role',
type: 'select',
defaultValue: 'user',
options: [
{ label: 'User', value: 'user' },
{ label: 'Admin', value: 'admin' },
],
},
],
}import { createSessionHelpers } from '@delmaredigital/payload-better-auth'
import type { User } from '@/payload-types'
export const { getServerSession, getServerUser } = createSessionHelpers<User>({
idType: 'text',
})Migrating from Postgres to MongoDB
Remove
generateId: 'serial' from your Better Auth config.Change
betterAuthStrategy() to betterAuthStrategy({ idType: 'text' }).Set
idType: 'text' on createSessionHelpers.Remove any explicit
idType: 'number' from payloadAdapter's adapterConfig.Switch Payload's database adapter to
mongooseAdapter.The atomic SQL path described in Atomic operations is Postgres-only. On MongoDB, consumeOne and incrementOne use the Local API.

