# A database for your app

This page is the whole answer to a vibecoded app with no database. It is the one most implementations leave half finished, because provisioning a Postgres is step one and writing a `DATABASE_URL` into the app is step two, and step two is where the user usually ends up holding a manual task.

## From an agent

Two tool calls, no credentials in the conversation, no dashboard. Ask your agent for a database and it should call these in order:

```
kraftify_ceiling()                    # is there room
kraftify_create_target(name: "app-db", kind: "postgres", size: "small")
kraftify_set_env(target: "app-db", key: "DATABASE_URL")
```

The third call records that the value is set. It never receives the value and never returns one, which is why there is nothing to redact before you paste the transcript anywhere.

## From a terminal

```
kraftify deploy --kind postgres --name app-db --size small
kraftify env set app-db DATABASE_URL
```

## Why Postgres

Because agents know Postgres. There is more training data for it than for anything else, so it is the database a coding agent reaches for without being told, and the one your ORM already speaks. If you have a reason to want something else, `--kind container --image` gets you there and the same tools see it.

## Migrations

Migrations run from your agent against the connection string it already holds. We do not proxy them, do not parse them and do not keep a migration history. Your agent knows how to run a migration; it needs somewhere to run it.

## What we hold

- The name of each env key, and whether one is set.
- A hash of the value, so we can tell you whether the value in force has changed.
- Never the value. There is no endpoint that returns it, because there is nothing stored to return.

Query logs are streamed to you and dropped at the socket, like console output. See [What we store](/docs/data).
