# What Database Options Does OpenSEO Support? D1 vs PostgreSQL Explained

> Explore OpenSEO database options: Cloudflare D1 for development and PostgreSQL for production. Easily switch providers using the DATABASE_PROVIDER environment variable.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: database-comparison
- Published: 2026-08-30

---

**OpenSEO supports Cloudflare D1 (SQLite) for zero-config development and PostgreSQL for production workloads, switchable via the `DATABASE_PROVIDER` environment variable.**

The `every-app/open-seo` repository implements a provider-aware data layer that abstracts database specifics behind a unified client interface. By supporting both serverless SQLite via Cloudflare D1 and full PostgreSQL instances, OpenSEO lets developers start on a free tier and scale to production without refactoring query logic. Understanding these OpenSEO database options allows you to choose the right backend for your traffic and complexity requirements.

## Supported Database Providers

### Cloudflare D1 (SQLite) — The Default

**D1** is the default provider, activated automatically when no explicit configuration is present. It stores data in a lightweight SQLite database managed by Cloudflare’s D1 service, which runs on their free tier. The default selection logic lives in [`src/db/provider.ts`](https://github.com/every-app/open-seo/blob/main/src/db/provider.ts), where the system initializes the D1 driver unless `DATABASE_PROVIDER=postgres` is detected.

### PostgreSQL — The Production Alternative

For applications requiring complex transactions, advanced indexing, or higher concurrency, OpenSEO supports **PostgreSQL** via the `postgres` provider. Enabling this requires setting the `DATABASE_PROVIDER` environment variable and configuring a Hyperdrive binding (or a local connection string for development). The provider logic in [`src/db/provider.ts`](https://github.com/every-app/open-seo/blob/main/src/db/provider.ts) exposes `getPostgresConnectionString()` for scripts that need direct database access.

## How the Provider Abstraction Works

OpenSEO centralizes database access through a single export in [`src/db/index.ts`](https://github.com/every-app/open-seo/blob/main/src/db/index.ts). This module resolves the active provider at runtime by checking the environment variable:

```ts
// src/db/index.ts
export const db = (getDatabaseProvider() === "postgres"
  ? pgDb
  : d1Db) as unknown as typeof d1Db;

```

This architecture ensures that application code remains database-agnostic. Whether you import `db` in an API route or a background job, the underlying engine (D1 or Postgres) is transparent to the consumer. TypeScript definitions in [`src/env.d.ts`](https://github.com/every-app/open-seo/blob/main/src/env.d.ts) enforce type safety by restricting `DATABASE_PROVIDER` to the union type `"d1" | "postgres"`.

## Configuring Your Database Environment

Control the active database by setting environment variables in your project root:

**Using D1 (Development):**

```env

# .env

DATABASE_PROVIDER=d1

```

**Using PostgreSQL (Production):**

```env

# .env.production

DATABASE_PROVIDER=postgres

```

Once configured, import the unified client anywhere in your server code:

```ts
// Any server function
import { db } from "@/db";

export async function getProjects() {
  // Identical syntax works for both D1 and Postgres
  return await db.select().from(projects).all();
}

```

If you need the raw Postgres connection string for external tooling or custom migrations, use the provider-specific helper:

```ts
import { getPostgresConnectionString } from "@/db/provider";

const connStr = getPostgresConnectionString(); 
// Throws if DATABASE_PROVIDER is not "postgres"

```

## Summary

- **Two supported backends**: Cloudflare D1 (SQLite) as the zero-config default and PostgreSQL as the opt-in production database.
- **Environment-driven switching**: Set `DATABASE_PROVIDER` to `"d1"` or `"postgres"` in your environment variables; [`src/db/provider.ts`](https://github.com/every-app/open-seo/blob/main/src/db/provider.ts) handles the resolution.
- **Database-agnostic queries**: Import `db` from [`src/db/index.ts`](https://github.com/every-app/open-seo/blob/main/src/db/index.ts) to write code that works regardless of the underlying engine.
- **Type safety**: [`src/env.d.ts`](https://github.com/every-app/open-seo/blob/main/src/env.d.ts) ensures compile-time checking of the provider selection.
- **Drizzle ORM integration**: Separate configuration files ([`drizzle.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle.config.ts) and [`drizzle-pg.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle-pg.config.ts)) manage schema migrations for each dialect.

## Frequently Asked Questions

### Is Cloudflare D1 free to use with OpenSEO?

Yes. D1 is the default provider in [`src/db/provider.ts`](https://github.com/every-app/open-seo/blob/main/src/db/provider.ts) and operates on Cloudflare’s free tier, making it ideal for prototyping and small-scale deployments without incurring database hosting costs.

### How do I switch from D1 to PostgreSQL in OpenSEO?

Set `DATABASE_PROVIDER=postgres` in your environment variables and ensure you have a Hyperdrive binding or valid connection string configured. No application code changes are required because the unified `db` export in [`src/db/index.ts`](https://github.com/every-app/open-seo/blob/main/src/db/index.ts) automatically switches the underlying driver based on the provider setting.

### What is Hyperdrive and why does PostgreSQL require it?

Hyperdrive is Cloudflare’s connection pooling service that optimizes latency and throughput to external databases. When using the `postgres` provider in production, OpenSEO expects a Hyperdrive binding to manage connections efficiently, though local development can use standard connection strings defined in your environment.

### Can I use both databases simultaneously in the same OpenSEO deployment?

No. The architecture uses a single provider resolution at runtime in [`src/db/index.ts`](https://github.com/every-app/open-seo/blob/main/src/db/index.ts). While the codebase is structured to support either provider, it does not support querying both D1 and Postgres in the same runtime instance; you must choose one provider via the `DATABASE_PROVIDER` variable.