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

# Postgres

> Declare managed Postgres, consume DATABASE_URL, and use pgvector and preview branches.

Declare Postgres in `floo.app.toml`. The next deploy provisions it and injects
the connection values. See [Managed services](/docs/guides/managed-services) for the
shared lifecycle: declaring, attaching credentials, and removal.

```toml floo.app.toml theme={null}
[managed.default]
type = "postgres"
```

## What gets injected

Default Postgres provides `DATABASE_URL` plus `PGHOST`, `PGPORT`, `PGDATABASE`,
`PGUSER`, and `PGPASSWORD`.

`DATABASE_URL` is a plain PostgreSQL URI
(`postgresql://user:password@host:port/database`), so Rails and Active Record,
Django, SQLAlchemy, Prisma, `pg`, and libpq consume it directly. The `PG*`
variables exist for libraries that prefer separate connection parameters.

Dev and prod are provisioned up front with different roles and passwords, against
the `_dev` and `_prod` schemas.

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

## Defaults and limits

Every managed Postgres service ships with the same defaults, there are no self-serve tiers to choose between:

| Setting                     | Default |
| --------------------------- | ------- |
| Max connections             | 25      |
| Statement timeout           | 60s     |
| Idle-in-transaction timeout | 120s    |
| Lock timeout                | 10s     |
| `work_mem`                  | 16 MB   |
| `temp_buffers`              | 32 MB   |

The `--tier` flag on `floo services add postgres` is accepted for backwards-compatibility but ignored, every value maps to the same defaults.

## Watching connection usage

floo tracks live Postgres connection usage and warns you before you hit the limit:

* **Dashboard**, the managed-Postgres panel shows `N / 25 connections in use` and surfaces a warning when you cross 75%.
* **CLI**, `floo db connections --app my-app [--env dev|prod]` prints the same data, with a `--json` mode for agents.
* **Email**, the org owners and admins get an email at 75% sustained, with a one-click `mailto:team@getfloo.com` for capacity requests. One email per app per 24h max.

Most apps that hit the cap either need connection pooling at the application layer (PgBouncer, SQLAlchemy pool tuning) or more raw capacity. If pooling isn't enough, email us.

## Vector search with pgvector

Managed Postgres ships with [pgvector](https://github.com/pgvector/pgvector)
enabled. The `vector` type resolves unqualified, so use it directly with no
`CREATE EXTENSION` and no schema prefix:

```sql theme={null}
CREATE TABLE documents (
  id bigserial PRIMARY KEY,
  embedding vector(1536)
);

SELECT id FROM documents ORDER BY embedding <-> $1 LIMIT 5;
```

Framework migrations work the same way. Rails `t.vector :embedding, limit: 1536`
(or the `neighbor` gem), Django, `pgvector.sqlalchemy`, and Prisma all reference
the bare type name. You never need `public.vector` or a manual extension step.

## Schema portability across dev and prod

Each environment gets its own schema, `app_<id>_dev` and `app_<id>_prod`, and the
role's `search_path` resolves unqualified table names automatically. Migrations
and queries carry no schema prefix and run unchanged in both.

One Rails caveat: `config.active_record.schema_format = :sql` dumps a
`structure.sql` that embeds the current schema name and its `search_path`. Keep
migrations schema-agnostic so a structure dumped against dev loads into prod. The
default `:ruby` format sidesteps this.

Release promotion without rebuilding runs each service's `migrate_command`
before changing any application revision. A migration failure blocks this
promotion. Old code continues serving against the
migrated schema until cutover; if cutover fails, that overlap can continue
indefinitely. There is no fixed overlap window.

Fresh deploys run migrations after deploying the new revisions: with traffic
staging enabled, those revisions receive no traffic until migrations and the
cutover checks pass; without staging, new code can serve before migration runs.
Do not assume the same ordering across deploy paths.

Use expand-then-contract migrations:

1. **Expand:** add nullable columns or new tables while preserving the schema
   used by the serving code. Keep both old and new code compatible with this
   schema.
2. **Backfill:** populate the new fields, keeping old and new representations in
   sync while writes continue; deploy code that can read both during the transition.
3. **Contract later:** remove or rename old fields in a later release, only after
   backfill is complete and no serving code or intended rollback version depends
   on them.

## Preview database branches

Each preview with managed Postgres gets its own database branch. Migrations and
writes there are isolated from dev, prod, and other previews.

```bash theme={null}
floo db branches list feat-db-abcde --app my-app
floo db branches show feat-db-abcde --app my-app --name default
```

Reset a branch to discard reviewer or agent changes:

```bash theme={null}
floo db branches reset feat-db-abcde --app my-app --name default --yes
```

Reset is preview-scoped. It destroys only that branch, leaves dev and prod
untouched, and reports `dev_prod_untouched` in `--json` output.

Preview data modes are `empty`, `seed`, and `clone-dev`. See
[Preview environments](/docs/guides/preview-environments#clone-dev).

## Debug a connection issue

```bash theme={null}
floo logs query --app my-app --error --since 30m
floo env list --app my-app
```

Check that the service needing data has `env.managed` including the Postgres
handle, that `DATABASE_URL` and `PGHOST` appear in `floo env list`, and that the
app reads env vars rather than a hard-coded local connection string.

<CardGroup cols={2}>
  <Card title="Managed services" href="/docs/guides/managed-services" icon="database">
    The shared lifecycle: declare, attach, inspect, remove.
  </Card>

  <Card title="Redis" href="/docs/guides/redis" icon="bolt">
    Cache and queue instances, and how handles map to databases.
  </Card>
</CardGroup>
