# Database

> A Postgres database per project, plus an empty development branch agents can use without touching production data.

The `database` resource is a Postgres database for the project. The app gets `DATABASE_URL` in its env (on Vibiz hosting, connected hosts, or through `VIBIZ_APP_KEY`). Any Postgres client, ORM or migration tool works: it is plain Postgres over the internet.

The **development copy** is a branch with production's tables and **none of its rows**: every table is emptied (the app's rows and sign-in's users and sessions), checked, and only then handed out. Migration ledgers (Drizzle's, Prisma's) are kept, so migrations don't run twice. That is the database agents and laptops use.

## Pricing

Usage records each ready database at an estimated $0.02 a day of cost, billed with the default margin (+20% today, `billed_usd` in usage) while pricing is not decided.

## Limits

- One database per project; a development branch per project.
- The read view (`/database`, `vibiz_database`) is read-only: one `SELECT`, `WITH`, `TABLE`, `VALUES`, `EXPLAIN` or `SHOW` statement, up to 20,000 characters, run for at most 5 seconds; it returns the first 500 rows (`truncated: true` past that). Table pages: up to 200 rows.
- Production rows are the app's users' data: only owner keys read them.

## Use it

```bash
vibiz dev                         # DATABASE_URL for the development branch, in .env.development.local
npx drizzle-kit migrate           # or prisma migrate, psql…: your own tools
```

```ts
import postgres from 'postgres';
const sql = postgres(process.env.DATABASE_URL!);
const rows = await sql`select id, email from users limit 10`;
```

Look at the data without a client:

```bash
curl "https://app.vibiz.app/v1/projects/$PROJECT/database?env=development" \
  -H "Authorization: Bearer $VIBIZ_API_KEY"
# → the schemas and tables, with row estimates

curl https://app.vibiz.app/v1/projects/$PROJECT/database/query \
  -H "Authorization: Bearer $VIBIZ_API_KEY" -H 'content-type: application/json' \
  -d '{"sql":"select table_name from information_schema.tables where table_schema = '\''public'\''","env":"development"}'
```

From an agent: `vibiz_database { project_id }` lists tables; `vibiz_database { project_id, sql }` runs one read-only statement against the development copy.

## What agents can and can't do

| | development | production |
| --- | --- | --- |
| `DATABASE_URL` | yes (`vibiz dev`) | no: owners only |
| List tables, read rows, read-only SQL | yes | no: `403 owner_only` |
| Write | with their own client and the development URL | never |

## Errors

| Code | Status | When | Next step |
| --- | --- | --- | --- |
| `invalid_request` | 400 | a statement that would write in the read view | use your own client against the development URL |
| `forbidden` + `owner_only` | 403 | an agent reading production rows | use `env=development` |
| `dependency_not_ready` | 409 | the database or its development copy isn't ready | `vibiz dev`, then retry |
