DarkDuck uses PostgreSQL via Drizzle ORM. There are three ways to run the database.
1. Embedded PostgreSQL (Default)
Zero config. If you don’t set DATABASE_URL, the server starts an embedded PostgreSQL instance automatically.
On first start, the server:
- Creates
~/.darkduck/instances/default/db/ for storage
- Ensures the
darkduck database exists
- Runs migrations automatically
- Starts serving requests
Data persists across restarts. To reset: rm -rf ~/.darkduck/instances/default/db.
The Docker quickstart also uses embedded PostgreSQL by default.
Embedded mode is ideal for development and single-machine deployments. It requires no external services and starts instantly.
2. Local PostgreSQL (Docker)
For a full PostgreSQL server locally:
This starts PostgreSQL 17 on localhost:5432. Set the connection string:
cp .env.example .env
# DATABASE_URL=postgres://darkduck:darkduck@localhost:5432/darkduck
Push the schema:
DATABASE_URL=postgres://darkduck:darkduck@localhost:5432/darkduck \
npx drizzle-kit push
3. Hosted PostgreSQL
For production, use a hosted provider like Supabase, Neon, or AWS RDS.
Create a database
Create a PostgreSQL 17 database with your provider.
Get the connection string
Copy the direct connection string (port 5432) for migrations and the pooled connection (port 6543) for the application.
Configure DarkDuck
Set DATABASE_URL in your .env or environment.
If using connection pooling, disable prepared statements:
// packages/db/src/client.ts
export function createDb(url: string) {
const sql = postgres(url, { prepare: false });
return drizzlePg(sql, { schema });
}
Use the direct connection (not pooled) for running migrations. Pooled connections may interfere with DDL statements.
Switching Between Modes
DATABASE_URL | Mode |
|---|
| Not set | Embedded PostgreSQL |
postgres://...localhost... | Local Docker PostgreSQL |
postgres://...supabase.com... | Hosted provider |
The Drizzle schema (packages/db/src/schema/) is the same regardless of mode. Migrations run automatically on server start.
Backups
For embedded mode, back up the entire database directory:
cp -r ~/.darkduck/instances/default/db ~/.darkduck/backups/$(date +%Y%m%d)
For external PostgreSQL, use standard pg_dump:
pg_dump $DATABASE_URL > backup.sql