> ## Documentation Index
> Fetch the complete documentation index at: https://voyant.travel/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Database

> Managed Postgres and D1 for apps you deploy on Voyant, provisioned for you — one as a connection string, the other as a Worker binding.

Voyant gives an app you deploy a managed database. There are two kinds, and they are consumed differently:

* **Managed Postgres** — injected as a connection string. Use any Postgres client. This is the default and matches the platform's tenancy model of one Postgres database per organization.
* **D1** — a SQLite database accessed through a Worker binding, the same way as [storage](/docs/services/storage).

<Note>
  Two command groups touch "the database" and do different things. `voyant databases` (this page) provisions and manages the **managed Cloud database**. `voyant db` runs **Drizzle Kit** against your project schema — `generate`, `migrate`, `studio`, `push`. You provision with the former and apply migrations with the latter.
</Note>

## Provisioning

A database is created when you create an app, but you can manage them directly:

```bash theme={null}
voyant databases list
voyant databases create my-db --kind neon   # default; use --kind d1 for Cloudflare D1
voyant databases get <id>
voyant databases delete <id> --yes
```

See the [CLI command reference](/docs/cli/commands) for every flag.

## Neon Postgres

When your app is deployed, Cloud injects a `DATABASE_URL` environment variable with a managed, pooled connection string. It is marked secret and is available to both the Worker and Node runtimes, so your code reads it the same way everywhere:

```ts theme={null}
const databaseUrl = process.env.DATABASE_URL!;
```

Connect with any standard Postgres client. A Voyant application uses Drizzle:

```ts theme={null}
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";

const pool = new Pool({ connectionString: process.env.DATABASE_URL });
export const db = drizzle(pool);
```

Use the pooled `DATABASE_URL` for application traffic. A direct (non-pooled) string is also injected as `DATABASE_URL_DIRECT` for the Node execution lane only — reach for it from tools that need a single long-lived session, such as certain migration or introspection tools. It is never shipped to the Worker runtime.

### Branches and connection strings

Managed Postgres supports branches, useful for previews and migrations:

```bash theme={null}
voyant databases branches <id>
voyant databases connection <id> --branch <branch>   # pooled by default
voyant databases connection <id> --direct            # non-pooled
```

## Cloudflare D1

D1 is provisioned with `--kind d1` and accessed through a Worker binding rather than a connection string. Declare the binding in your `wrangler.jsonc`; the deploy resolves it to your provisioned database:

```jsonc theme={null}
{
  "d1_databases": [{ "binding": "DB", "database_name": "my-db" }]
}
```

Then query it through the binding with Cloudflare's D1 API:

```ts theme={null}
const { results } = await env.DB.prepare(
  "SELECT * FROM bookings WHERE id = ?",
).bind(bookingId).all();
```

See Cloudflare's [D1 Workers API reference](https://developers.cloudflare.com/d1/worker-api/) for the full surface. Cloud derives the binding name by upper-casing the resource name and turning dashes into underscores (`my-db` → `MY_DB`).

## Migrations

For Postgres, migrations are part of your app, not a Cloud step you run by hand. Author them against your schema with Drizzle Kit and the deploy applies them:

```bash theme={null}
voyant db generate   # create a migration from schema changes
voyant db migrate    # apply pending migrations
voyant db studio     # browse data locally
```

Deploys run pending migrations as part of shipping a release. A failing migration blocks the deploy, so your code never ships ahead of a schema it depends on.

## Next steps

<CardGroup cols={2}>
  <Card title="Storage" icon="bucket" href="/docs/services/storage">
    Object storage (R2) and key-value (KV).
  </Card>

  <Card title="CLI commands" icon="terminal" href="/docs/cli/commands">
    Every `databases` and `db` subcommand and flag.
  </Card>
</CardGroup>
