Skip to main content
Declare Postgres in floo.app.toml. The next deploy provisions it and injects the connection values. See Managed services for the shared lifecycle: declaring, attaching credentials, and removal.
floo.app.toml

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.

Defaults and limits

Every managed Postgres service ships with the same defaults, there are no self-serve tiers to choose between: 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 enabled. The vector type resolves unqualified, so use it directly with no CREATE EXTENSION and no schema prefix:
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.
Reset a branch to discard reviewer or agent changes:
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.

Debug a connection issue

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.

Managed services

The shared lifecycle: declare, attach, inspect, remove.

Redis

Cache and queue instances, and how handles map to databases.