How to Configure OpenSEO for D1/SQLite Database: 5-Step Setup Guide

Set DATABASE_PROVIDER=d1 (or leave it unset), run pnpm run db:migrate:local, and start the dev server to run OpenSEO on Cloudflare D1 (SQLite) — no PostgreSQL required.

OpenSEO is an open-source SEO management platform built for Cloudflare Workers that supports two data stores: Cloudflare D1 (SQLite) and PostgreSQL. The D1/SQLite configuration is the default and simplest way to get started, whether you're running locally or deploying to production. This guide walks through the exact configuration steps based on the OpenSEO source code, with references to specific files and implementation details.

Set the Database Provider in Environment Variables

OpenSEO detects your database backend through the DATABASE_PROVIDER environment variable. For D1/SQLite, you have two options:

  • Recommended: Omit DATABASE_PROVIDER entirely — D1 is the default
  • Explicit: Set DATABASE_PROVIDER=d1 in your .env.local or wrangler.toml

The provider detection logic lives in src/db/provider.ts. This file exports getDatabaseProvider(), which returns "d1" or "postgres" and determines which driver and schema set the application loads.


# .env.local

DATABASE_PROVIDER=d1
AUTH_MODE=local_noauth

With AUTH_MODE=local_noauth, you bypass BetterAuth for local development — this mode works seamlessly with the D1 store without additional authentication configuration.

Verify the SQLite Schema Files

When DATABASE_PROVIDER resolves to "d1", OpenSEO automatically loads the SQLite schema files located in src/db/*.schema.ts. Key files include:

  • src/db/app.schema.ts — Core application tables
  • Other *.schema.ts files in src/db/ — Feature-specific table definitions

These files define the Drizzle ORM schema used when the provider is SQLite. No manual configuration is required; the schema is imported automatically based on the provider selection.

Run D1 Database Migrations

Once your environment variables are set, create the local D1 database by running the migration command:

pnpm run db:migrate:local

This executes Drizzle migration scripts against the SQLite file bound to your local Worker environment. The migration creates all necessary tables according to the SQLite schema definitions.

After the initial migration, subsequent schema changes are handled through Drizzle's migration system — run the same command to apply updates.

Start the Development Server

With migrations complete, launch the development server using one of these commands:


# Standard development server

pnpm run dev

# Agents-friendly server (recommended for most setups)

pnpm dev:agents

The dev:agents variant is optimized for development environments using agent-based workflows and is the recommended approach in the LOCAL_DEVELOPMENT.md documentation.

How the D1 Database Adapter Works

The actual database connection and Drizzle adapter creation happens in src/lib/auth.ts. Here's the implementation that switches between PostgreSQL and SQLite:

const database =
  getDatabaseProvider() === "postgres"
    ? drizzleAdapter(pgDb, { provider: "pg", schema: pgSchema })
    : drizzleAdapter(d1Db, { provider: "sqlite", schema: d1Schema });

When getDatabaseProvider() returns "d1" (the default), the code:

  1. Uses d1Db — the D1 database binding passed through the execution context
  2. Sets provider: "sqlite" — tells Drizzle to use SQLite dialect
  3. Loads d1Schema — the SQLite-specific schema definitions from src/db/*.schema.ts

This architecture allows OpenSEO to maintain dual database support with a single codebase. The conditional logic in src/lib/auth.ts and src/db/provider.ts handles the abstraction, so your application code remains provider-agnostic.

Optional: Switch to PostgreSQL Later

If you need to migrate from D1 to PostgreSQL in the future, change a single environment variable:

DATABASE_PROVIDER=postgres

You'll also need to provide a Hyperdrive binding or local connection string for PostgreSQL. The same adapter code in src/lib/auth.ts automatically switches to the Postgres Drizzle adapter when the provider changes — no other code modifications required.

Summary

  • D1 is the default: Leave DATABASE_PROVIDER unset or explicitly set it to "d1" to use SQLite
  • Three key files control the setup: src/db/provider.ts (detection), src/lib/auth.ts (adapter creation), and src/db/*.schema.ts (table definitions)
  • Two commands to start: pnpm run db:migrate:local then pnpm dev:agents
  • Auth mode matters: Use AUTH_MODE=local_noauth for frictionless local D1 development
  • Future-proof: One environment variable change switches the entire stack to PostgreSQL

Frequently Asked Questions

What is the default database provider in OpenSEO?

D1 (SQLite) is the default database provider. If you don't set DATABASE_PROVIDER, getDatabaseProvider() in src/db/provider.ts returns "d1" and the application initializes with SQLite bindings. This design prioritizes the simplest local development experience and aligns with Cloudflare's edge-native architecture.

Can I use OpenSEO with D1 without any authentication setup?

Yes. Set AUTH_MODE=local_noauth in your environment variables. This mode bypasses the BetterAuth integration entirely and allows you to interact with the D1 database without configuring OAuth providers, sessions, or user management. It's the recommended approach for initial local development.

Where does the actual database connection happen in the OpenSEO codebase?

The database adapter is instantiated in src/lib/auth.ts using Drizzle's adapter pattern. The code evaluates getDatabaseProvider() and creates either a PostgreSQL adapter (provider: "pg") or SQLite adapter (provider: "sqlite"). The d1Db binding comes from the Cloudflare Workers environment, injected at runtime through Wrangler's local dev server or production deployment.

Is there any performance difference between D1 and PostgreSQL in OpenSEO?

For typical SEO management workloads — crawling, indexing status tracking, and metadata storage — D1 performs well within Cloudflare's edge network. The same Drizzle ORM queries execute against both backends. PostgreSQL becomes advantageous for complex analytical queries, high-volume concurrent writes, or when you need specific Postgres extensions. The abstraction in OpenSEO allows you to start with D1 and migrate to PostgreSQL without rewriting application code.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →