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:
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.
(app, type, name) already exists. Prefer config declarations for normal desired-state authoring.
Attach credentials to services
Infloo.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:
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.
--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 afailedrow 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.
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:
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:
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.