--- title: "Database — SQLite" aliases: [sqlite-adapter, payload-sqlite, db-sqlite] tags: [payloadcms, database, sqlite, drizzle, libsql, turso, cloudflare-d1] sources: [raw/database__sqlite.md] created: 2026-05-15 updated: 2026-05-15 --- ## Overview Payload supports SQLite via `@payloadcms/db-sqlite`, built on **Drizzle ORM** + **libSQL**. Auto-manages schema changes in dev mode; full migration controls for other environments. ```ts import { sqliteAdapter } from '@payloadcms/db-sqlite' export default buildConfig({ db: sqliteAdapter({ client: { url: process.env.DATABASE_URL, authToken: process.env.DATABASE_AUTH_TOKEN, // for Turso }, }), }) ``` ## Key Options | Option | Default | Notes | |--------|---------|-------| | `client` * | — | `{ url, authToken }` passed to `createClient` from `@libsql/client` | | `push` | `true` (dev only) | Disable Drizzle db push in development | | `migrationDir` | — | Custom migration directory | | `idType` | `'number'` | `'number'` or `'uuid'` | | `transactionOptions` | — | `SQLiteTransactionConfig` or `false` to disable | | `localesSuffix` | `'_locales'` | Table name suffix for localized fields | | `relationshipsSuffix` | `'_rels'` | Table name suffix for relationships | | `versionsSuffix` | `'_v'` | Table name suffix for versions | | `autoIncrement` | `false` | SQLite AUTOINCREMENT — prevents ID reuse from deleted rows | | `blocksAsJSON` | `false` | Store blocks as JSON instead of relational tables (perf boost for many blocks) | | `busyTimeout` | `0` | ms to wait when DB is locked | | `wal` | `false` | Enable WAL mode — see [[wiki/payloadcms/database-sqlite#wal-mode\|WAL Mode]] | | `beforeSchemaInit` | — | Hook before schema build | | `afterSchemaInit` | — | Hook after schema build | | `generateSchemaOutputFile` | `src/payload-generated.schema.ts` | Override generated schema path | | `allowIDOnCreate` | `false` | Accept `id` in create operations without custom ID field | ## Dev Mode — db push vs Migrations - **db push** (default): auto-syncs schema changes to DB, no manual migration needed; warns on data loss - **Migrations only**: set `push: false` — use `payload migrate` commands exclusively - Do **not** mix push and manual migrate commands See [[wiki/payloadcms/database-migrations|Database Migrations]] for full CLI reference. ## Drizzle Direct Access Generate types first: ```sh npx payload generate:db-schema ``` Then query directly: ```ts import { posts } from './payload-generated-schema' import { eq, sql, and } from '@payloadcms/db-sqlite/drizzle' // Relational API const posts = await payload.db.drizzle.query.posts.findMany() // Select API const result = await payload.db.drizzle .select() .from(posts) .where(and(eq(posts.id, 50), sql`lower(${posts.title}) = 'example post title'`)) ``` Exposed on `payload.db`: - `payload.db.drizzle` — Drizzle instance - `payload.db.tables` — all tables - `payload.db.relations` — all relations ## Schema Hooks ### beforeSchemaInit Runs before schema is built. Use to add tables Payload doesn't manage (e.g. preserving existing DB structure when migrating to Payload). ```ts sqliteAdapter({ beforeSchemaInit: [ ({ schema, adapter }) => { return { ...schema, tables: { ...schema.tables, addedTable: sqliteTable('added_table', { id: integer('id').primaryKey({ autoIncrement: true }), }), }, } }, ], }) ``` Tip: use [Drizzle Introspection](https://orm.drizzle.team/kit-docs/commands#introspect--pull) to generate schema from an existing DB, then import into `beforeSchemaInit`. To include custom tables/columns in `payload generate:db-schema` output, mutate `adapter.rawTables` inside `beforeSchemaInit`: ```ts adapter.rawTables.posts.columns.customColumn = { name: 'custom_column', type: 'integer', notNull: true, } ``` ### afterSchemaInit Runs after schema is built. Use `extendTable` utility to add columns or composite indexes not in Payload config: ```ts sqliteAdapter({ afterSchemaInit: [ ({ schema, extendTable }) => { extendTable({ table: schema.tables.places, columns: { extraIntegerColumn: integer('extra_integer_column') }, extraConfig: (table) => ({ country_city_idx: index('country_city_idx').on(table.country, table.city), }), }) return schema }, ], }) ``` Note: columns/tables added in `afterSchemaInit` won't appear in `generate:db-schema` output — only `beforeSchemaInit` + `rawTables` mutation achieves that. ## WAL Mode Write-Ahead Logging improves performance and concurrency: ```ts db: sqliteAdapter({ wal: true, // or object with settings client: { url: process.env.DATABASE_URL }, }) ``` | WAL Setting | Default | Notes | |-------------|---------|-------| | `journalSizeLimit` | `67108864` (64MB) | WAL file size before checkpointing | | `synchronous` | `'FULL'` | `EXTRA` / `FULL` / `NORMAL` / `OFF` — perf vs safety tradeoff | ## Cloudflare D1 (Beta) Serverless SQLite via `@payloadcms/db-d1-sqlite`: ```ts import { sqliteD1Adapter } from '@payloadcms/db-d1-sqlite' export default buildConfig({ db: sqliteD1Adapter({ binding: cloudflare.env.D1, readReplicas: 'first-primary', // optional, experimental }), }) ``` - Inherits all SQLite adapter options except `client` (uses `binding` instead) - Read replicas: `'first-primary'` strategy — writes always go to primary - Must enable read replication in Cloudflare dashboard separately ## Key Takeaways - SQLite adapter uses Drizzle ORM + libSQL — supports local files, Turso, and Cloudflare D1 - **Dev mode**: `push: true` auto-syncs schema — don't mix with manual migrations - **Production**: use migrations exclusively (`push: false`) - Direct Drizzle access via `payload.db.drizzle` — generate types first with `npx payload generate:db-schema` - `beforeSchemaInit` for adding non-Payload tables (e.g. DB migration); `afterSchemaInit` for extending Payload tables - Only `rawTables` mutation in `beforeSchemaInit` propagates to generated schema file - WAL mode (`wal: true`) recommended for concurrent read-heavy workloads - `blocksAsJSON: true` can improve performance when using many blocks - `autoIncrement: true` prevents ID reuse — useful for audit/compliance scenarios - Cloudflare D1 adapter is beta — same API, `binding` instead of `client` ## Sources - `raw/database__sqlite.md` — official Payload CMS SQLite documentation ## Related - [[wiki/payloadcms/database-overview|Database — Overview]] - [[wiki/payloadcms/database-postgres|Database — Postgres]] - [[wiki/payloadcms/database-mongodb|Database — MongoDB]] - [[wiki/payloadcms/database-migrations|Database Migrations]] - [[wiki/payloadcms/database-indexes|Database Indexes]]