Skip to main content
floo runs four things for you, so your app does not have to bring them. Postgres and Storage hold persistent data. Declare Postgres, Redis, and Storage with [managed.<name>] blocks and a deploy provisions what is missing. Managed Redis is cache-only: treat its contents as disposable. floo makes no backup, restore, or durability guarantee for it; keep authoritative data in Postgres. Auth is the exception to that pattern. floo runs the sign-in flow for you the same way it runs a database, but it holds no data of yours, so it is a property of the app rather than a [managed] block. Turn it on with access_mode. The rest of this page covers the lifecycle the three stateful services share. Removing a deployed declaration is a tier-3 proposal. By default, the deploy proceeds and the resource keeps working without a teardown schedule. An explicit approval policy requires human review; approved Redis and Storage removals receive a rescindable schedule. Postgres receives no schedule. Deploy does not delete data. Completing deletion still requires the explicit floo services remove executor with confirmation for the exact resource.

Provision a service

Declare managed-service intent next to the app shape:
Then preflight, commit, and push:
The deploy provisions the underlying resources and injects their generated env vars. Connection credentials never enter git. Connection credentials are never stored in floo.app.toml. They’re synthesized at deploy time and injected directly into the runtime environment. Use [managed.default] for the one service that should receive the unsuffixed conventional keys. TOML block names are unique, so additional resource types need names and receive suffixed keys. Only default Postgres receives the PG* component variables.

Operational provisioning for an existing app

floo services add is the explicit operational lane for an app that already exists. It requires app context and is not the fresh-app workflow.
The command returns HTTP 409 if (app, type, name) already exists. Prefer config declarations for normal desired-state authoring.

Attach credentials to services

In floo.app.toml, put attachments under [services.NAME.env], including for single-service apps. Both parsers ignore top-level [env] without error, so an existing [env] managed = [] no longer opts out; move it under [services.NAME.env]. managed = [] opts that service out:
Handles map to generated env vars: postgres gives DATABASE_URL plus PG*, redis gives REDIS_URL, and storage gives STORAGE_BUCKET plus STORAGE_URL. Named services use type:name, such as postgres:analytics for DATABASE_URL_ANALYTICS. A named Postgres service receives only its suffixed URL, not the PG* component variables. If no service declares managed, floo keeps legacy all-service injection. Once any service declares it, services without managed receive no managed-service credentials. floo only strips keys owned by managed-service records, so an external user-managed DATABASE_URL is not swept up by this filter. floo preflight --json shows the exact per-service plan in env_injection_plan.

Inspect

Remove

For a config-declared service, start with a pull request that removes the matching [managed.<name>] block. floo preflight --json classifies it as to_deprovision, and the floo/infra-approval check follows the account’s effective approval policy. The shared default requires no review and retains the resource without a teardown schedule. Setting enabled = false makes the same removal proposal. Renaming a block proposes creation under the new name and removal of the old resource. When an explicit policy requires review, approval and merge make floo schedule a rescindable teardown for Redis and Storage; re-declaring the service cancels it. Postgres receives no teardown schedule. No timer deletes data automatically. Complete terminal deletion with floo services remove. For a CLI-added resource that was never declared in config, this is the direct explicit deletion path.
The flag name is deliberately verbose. Destroying user data must be an explicit, acknowledged decision. There is no --force.

Dev and prod isolation

Each service type isolates dev from prod differently. Read this before promoting to prod. If your Storage service was created before dev/prod Storage isolation landed and data separation matters, email team@getfloo.com. We can inspect the row and backfill a dedicated prod bucket. Redis needs no backfill: a legacy single-database Redis converges on its next prod preparation.

Preflight reconciliation

floo preflight shows the planner’s view of managed-service state:
  • to_provision: declared in config but no row exists. The next deploy creates it.
  • to_retain: declared and present. Safe declared fields are reconciled.
  • to_retry: declared and a failed row exists. The next deploy retries the same row.
  • to_deprovision: previously config-declared, now removed or disabled. This is tier-3. By default, the resource remains live without review or a schedule. An explicit policy requires review; approval schedules a rescindable teardown for Redis and Storage, but not Postgres. Deploy does not delete data.
  • to_orphan: exists but was never config-declared, such as a CLI-added row. It remains live until explicitly removed.
  • in_flight_deprovisioning: a terminal deletion is in progress and is excluded from retain/orphan classification.
The distinction between to_deprovision and to_orphan preserves review history without inventing permission to destroy data.

Declare services in config ([managed.<name>])

If you’d rather keep managed-service intent in floo.app.toml alongside the rest of your app shape, declare each one as a [managed.<name>] block. <name> is a logical instance name, so you can declare more than one of a type:
A deploy provisions any declared service that doesn’t exist yet. Removing a previously deployed block produces the reviewed to_deprovision flow described above. It never performs terminal deletion by itself. This is the modern replacement for the legacy top-level [postgres] / [redis] / [storage] sections below. Full field reference: config spec.

Legacy TOML sections (deprecated)

Earlier versions of floo accepted [postgres], [redis], and [storage] top-level sections in floo.app.toml as a declarative shortcut:
These sections still auto-provision on first deploy during the deprecation window, but every deploy that processes them emits a warning. Run floo services add for each legacy service type declared in your app:
add provisions a missing resource. If the create endpoint returns a MANAGED_SERVICE_ALREADY_EXISTS 409, it resolves the existing row and reports it as already provisioned, with already_provisioned: true in JSON. Replace the legacy sections with [managed.<name>] declarations in floo.app.toml; declarations come from the manifest. After the sunset date, the parser will ignore the legacy sections entirely. Apps that haven’t migrated keep their managed services (the CLI sees them via floo services list); only the authoring surface changes.

Usage metering

Managed Postgres and Storage are included at no charge today. Managed Redis is passed through at provider cost, and the CPU and memory your services burn are metered as usual. Pricing is the single source for what is metered, what a credit is, and what the default shapes cost.

Postgres

Connection values, pgvector, and preview database branches.

Storage

Upload, download, and signed URL patterns.

Cron jobs

Schedule recurring tasks inside your app’s containers.