Any Postgres works in principle, but the shipped persistence adapters and
migrations target Supabase. A self-hosted Supabase behaves identically to
Supabase Cloud only the project URL differs.
Steps
1
Create a project
Create a free project at supabase.com/dashboard.
Pick a region close to your app’s servers to keep persistence writes fast.
2
Apply the schema one file
Open the Supabase SQL Editor, paste
packages/config-schema/supabase/schema.sql,
and run it once. That single script creates every table, index, trigger, and
the default policies firstflow_experiences, firstflow_flow_runs,
firstflow_llm_calls, firstflow_traces, firstflow_conversations, and
firstflow_conversation_messages.It is idempotent (if not exists throughout), so re-running it is safe.3
Collect the keys
From Settings → API, copy these into your app’s environment:
The
anon key is what the browser runtime uses to persist flow runs (governed
by RLS). The service_role key bypasses RLS
and is used only by @firstflow/runtime-server on your backend. Treat it
like a database superuser password never ship it to the browser, never
commit it. See Configuration.4
Verify the schema
In Table Editor you should see the
firstflow_* tables. A quick smoke
test: run an experience in your app and confirm a row appears in
firstflow_flow_runs; wrap one LLM call and confirm a row in
firstflow_llm_calls.Strict RLS (optional)
By default the policies are permissive the browser writes flow runs with theanon key and your app is the trust boundary. If you use Supabase Auth and
want flow-run writes locked to the signed-in user, uncomment the STRICT RLS
block at the bottom of schema.sql (it scopes writes to auth.uid()). See
Row Level Security.
Upgrading later
When you bump@firstflow/config-schema, apply any new numbered files from
migrations/
that you haven’t run yet, in order. There is no automatic runner applying SQL
to your own database stays under your control. Re-running schema.sql is also
safe and brings a project up to the latest shape.
Next
Continue to Configuration for the full environment reference, then Row Level Security to lock down who can read and write thefirstflow_* tables.