> ## 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.

# Managed Postgres and Redis on floo

> Provision Postgres and Redis with `floo services add`, consume `DATABASE_URL` and `REDIS_URL`, and debug them on floo.

Use this guide when your app needs a managed database or cache.

## 1. Provision The Services

```bash theme={null}
floo services add postgres --app my-app
floo services add redis --app my-app
```

Both commands are idempotent — re-running is safe. Each provisions the underlying resource, injects the matching env vars into your app, and updates `.floo/services.lock`. Commit the lock file alongside other changes.

For Postgres, both dev and prod credentials are provisioned up front. Dev reads a standard `DATABASE_URL` plus `PGHOST`, `PGPORT`, `PGDATABASE`, `PGUSER`, and `PGPASSWORD` for the `_dev` schema; prod gets a different role/password for the `_prod` schema. New Redis services also get isolated dev and prod databases. See [Managed Services → Dev and prod isolation](/docs/guides/managed-services#dev-and-prod-isolation).

The default Postgres role allows 25 active connections — enough for most Cloud Run apps. If you sustainedly need more, email [team@getfloo.com](mailto:team@getfloo.com?subject=Capacity%20request) and we'll provision a dedicated instance. The dashboard and `floo db connections --app my-app` show live usage.

## 2. Ship The First Deploy

```bash theme={null}
floo preflight --json
floo apps github connect owner/repo --app my-app
floo deploys watch --app my-app
```

The first deploy bakes the env vars into the runtime. Subsequent deploys reuse the existing managed-service rows.

For multi-service apps, attach the credentials to the services that need them:

```toml theme={null}
[services.api.env]
managed = ["postgres", "redis"]

[services.web.env]
managed = []
```

`floo preflight --json` shows the exact per-service env plan in `env_injection_plan`.

## 3. Read The Injected Values

```bash theme={null}
floo env list --app my-app
floo env get DATABASE_URL --app my-app
floo env get PGHOST --app my-app
floo env get REDIS_URL --app my-app
```

Use `env list` when you want masked visibility and `env get` when you need the plaintext value.

## 4. Consume Them In App Code

<CodeGroup>
  ```javascript Node.js theme={null}
  const databaseUrl = process.env.DATABASE_URL;
  const redisUrl = process.env.REDIS_URL;
  ```

  ```python Python theme={null}
  import os

  database_url = os.environ["DATABASE_URL"]
  redis_url = os.environ["REDIS_URL"]
  ```

  ```go Go theme={null}
  databaseURL := os.Getenv("DATABASE_URL")
  redisURL := os.Getenv("REDIS_URL")
  ```
</CodeGroup>

`DATABASE_URL` is intentionally a boring PostgreSQL URI (`postgresql://user:password@host:port/database`) so Rails/ActiveRecord, Django, SQLAlchemy, Prisma, `pg`, and libpq can consume it directly. The `PG*` vars are there for libraries or tools that prefer separate connection parameters.

## Redis: Shared By Default, Named When You Need Separation

A managed Redis handle maps to exactly one instance, so every service that declares `managed = ["redis"]` receives the **same** `REDIS_URL`. A web process enqueuing a job and a worker process draining it share one Redis by construction — no coordination, no "are they really the same instance?" guesswork.

To run separate instances — say, cache eviction that never touches your job queue — declare named ones in `floo.app.toml`:

```toml theme={null}
[managed.cache]
type = "redis"

[managed.queue]
type = "redis"
```

These inject `REDIS_URL_CACHE` and `REDIS_URL_QUEUE` — two physically separate databases. floo's managed Redis is one logical database per instance (there is no `SELECT n` index switching), so the way to separate concerns is named instances, not DB indexes. A Rails app can point its cache store at `REDIS_URL_CACHE` and Sidekiq + Action Cable at `REDIS_URL_QUEUE`, or share a single `REDIS_URL` across all three.

## Vector Search With pgvector

Managed Postgres ships with [pgvector](https://github.com/pgvector/pgvector) already enabled, so you can store and query embeddings with no setup. The `vector` type resolves unqualified, so use it directly in migrations and queries without `CREATE EXTENSION` and without a 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. In Rails, `t.vector :embedding, limit: 1536` (or the `neighbor` gem) emits a bare `vector` column and runs as-is. Django, SQLAlchemy (`pgvector.sqlalchemy`), and Prisma all reference the type by its bare name too. You never need `public.vector` or a manual extension step.

## Schema Portability Across Dev And Prod

floo gives each environment its own Postgres schema (`app_<id>_dev` in dev, `app_<id>_prod` in prod) and sets the role's `search_path` so your **unqualified** table names resolve automatically. Migrations and queries carry no schema prefix and run unchanged in both environments — your app never references the schema name.

One Rails caveat: if you set `config.active_record.schema_format = :sql`, the dumped `structure.sql` embeds the current environment's schema name and its `search_path` line. Keep migrations schema-agnostic (the default — never hardcode a schema) so a structure dumped against dev loads cleanly into prod. The default `:ruby` schema format (`schema.rb`) sidesteps this entirely.

## 5. Debug A Connection Issue

If the app is live but cannot reach its backing service:

```bash theme={null}
floo logs --app my-app --error --since 30m
floo env get DATABASE_URL --app my-app
floo env get REDIS_URL --app my-app
floo redeploy --restart --app my-app
```

Check:

* the managed services exist in `floo services list`
* the service that needs the database has `env.managed = ["postgres"]`
* `DATABASE_URL`, `PGHOST`, and `REDIS_URL` exist in `floo env list`
* the app is using env vars instead of hard-coded local connection strings
* runtime logs match the connection failure you expect

## Preview Database Branches

When pull request previews are enabled, each preview with managed Postgres gets its own preview database branch. Migrations and writes in that preview are isolated from dev, prod, and other previews.

Inspect branches:

```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 preview branch when reviewer or agent changes should be discarded:

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

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

Supported preview data modes are `empty`, `seed`, and `clone-dev`, which copies dev data for every attached managed Postgres, Redis, and Storage resource. Raw prod clone and sanitized prod clone are not V1 behavior. See [Preview Environments](/docs/guides/preview-environments#clone-dev).

<CardGroup cols={2}>
  <Card title="Managed Services Setup" href="/docs/guides/managed-services">
    Start from the exact `floo services` commands for managed services.
  </Card>

  <Card title="Preview Environments" href="/docs/guides/preview-environments">
    Inspect and reset preview database branches.
  </Card>

  <Card title="Environment Variables" href="/docs/guides/environment-variables">
    See how injected values appear in the CLI and when to override them.
  </Card>
</CardGroup>
