Skip to main content
floo runs four services your app would otherwise bring itself. Managed Storage follows paygo spending restrictions: exhausted funds or a monthly hard limit block new spending, and a hard stop disables S3 keys. Postgres and Storage hold persistent data. Declare Postgres, Redis, and Storage with [managed.<name>] blocks; 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 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 requires the explicit floo services remove executor with confirmation for the exact resource.

Provision a service

Then preflight, commit, and push:
The deploy provisions the resources and injects their generated env vars. Connection credentials never enter git or floo.app.toml. floo synthesizes them at deploy time and injects them into the runtime environment. [managed.default] is the one service that receives the unsuffixed conventional keys. TOML block names are unique, so additional resources 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 operational lane for an app that already exists. It requires app context and is not the fresh-app workflow.
If (app, type, name) already exists, the command reports the existing row instead of creating a duplicate. 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. The CLI rejects top-level [env] as an unknown key; the deploy parser ignores it with an unknown_manifest_key warning. Move [env] managed = [] 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 the STORAGE_S3_* keys. 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 strips only 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, open 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, as described at the top of this page. Setting enabled = false makes the same removal proposal. Renaming a block proposes creation under the new name and removal of the old resource. Re-declaring a service cancels its scheduled teardown. 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 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 predates dev/prod Storage isolation 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.
Keeping to_deprovision separate from to_orphan preserves review history without inventing permission to destroy data.

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

<name> is a logical instance name, so you can declare more than one of a type, as in Provision a service. Removing a previously deployed block produces the to_deprovision flow above and never performs terminal deletion by itself. This replaces 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:
These sections still auto-provision on first deploy during the deprecation window, and 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. Then replace the legacy sections with [managed.<name>] declarations in floo.app.toml. After the sunset date, the parser will ignore the legacy sections entirely. Apps that haven’t migrated keep their managed services (floo services list shows them); only the authoring surface changes.

Usage metering

Managed Postgres compute and storage, managed Redis usage, file storage, and the CPU and memory your services use are metered. Postgres compute is billed for every database that runs, including dev and preview databases, not only prod. Overwritten and deleted object versions are kept for 30 days and count toward stored bytes. Rates and plans are on getfloo.com/pricing.

Postgres

Connection values, pgvector, and preview database branches.

Storage

Read and write objects, and serve them through your app.

Cron jobs

Schedule recurring tasks inside your app’s containers.