Skip to main content
Use this guide when your app needs a managed database or cache.

1. Provision The Services

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. The default Postgres role allows 25 active connections — enough for most Cloud Run apps. If you sustainedly need more, email team@getfloo.com and we’ll provision a dedicated instance. The dashboard and floo db connections --app my-app show live usage.

2. Ship The First Deploy

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:
floo preflight --json shows the exact per-service env plan in env_injection_plan.

3. Read The Injected Values

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

4. Consume Them In App Code

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

Managed Services Setup

Start from the exact floo services commands for managed services.

Preview Environments

Inspect and reset preview database branches.

Environment Variables

See how injected values appear in the CLI and when to override them.