title: Remove ControlPlane (pgflow edge function) — startup compilation makes it redundant
labels: enhancement, pkgs/edge-worker, pkgs/cli, pkgs/website
Summary
Drop the ControlPlane (supabase/functions/pgflow/index.ts → ControlPlane.serve(flows)), its pgflow compile CLI command, and all supporting code/docs. Startup compilation covers everything the ControlPlane does, works reliably, and is already the documented preferred path.
Docs already pre-announce this: manual-compilation.mdx and compile-api.mdx both carry a deprecation notice — "Manual compilation via ControlPlane may be removed in a future release. Startup Compilation is the preferred approach."
What ControlPlane actually is
ControlPlane.serve(flows) starts a Deno.serve HTTP handler exposing a single endpoint:
GET /flows/:slug → compileFlow(flow) → { flowSlug, sql: string[] }
Code: pkgs/edge-worker/src/control-plane/ (index.ts, server.ts).
Exactly one consumer exists: the pgflow compile CLI command (pkgs/cli/src/commands/compile/index.ts), which fetches SQL from the endpoint and writes a timestamped migration file supabase/migrations/{timestamp}_create_{slug}_flow.sql.
No other caller found: no CI workflows, no examples, no runtime path. Worker management (ensure_workers() cron + track_worker_function) pings worker functions, never the pgflow function. deploy-first-flow.mdx already states the ControlPlane function "is for local compilation only and is not needed in production."
Why startup compilation fully covers it
FlowWorkerLifecycle.acknowledgeStart() → Queries.ensureFlowCompiled() → pgflow.ensure_flow_compiled() (pkgs/core/schemas/0100_function_ensure_flow_compiled.sql) is complete and safe:
- advisory lock (
pg_advisory_xact_lock) serializes concurrent worker starts for the same flow
- flow missing → compiled (both environments)
- shape match →
verified
- shape mismatch → local or
allowDataLoss: true → delete + recompile; production → mismatch → worker throws FlowShapeMismatchError and refuses to start
The versioned-flow workflow (build/version-flows.mdx) also works without migrations: a versioned flow (greetUserV2) is a new slug → "missing" → compiled at startup, even in production. The only prohibited case (mutating an existing flow's shape) is blocked by ensure_flow_compiled itself.
The get-started tutorial (quickstart, create-flow, run-flow) is 100% startup-compilation based already.
Removal checklist
pkgs/cli
pkgs/edge-worker
apps/demo
pkgs/website
pkgs/dsl
Caveats
- Migration-file workflow is lost. Teams putting flow SQL in source control for CI review lose
pgflow compile. Mitigation exists and is documented: compileFlow() from @pgflow/dsl (published to npm, runs in Node). With startup compilation the schema changes at worker boot, not via reviewed migration — a philosophical regression for strict CI shops, a non-issue for everyone else. This is the only substantive trade-off.
- Breaking change accounting.
ControlPlane is a public export of @pgflow/edge-worker (JSR + npm) — semver-major for that package. Old CLIs (pgflow@0.9–0.15 compile) run against a freshly installed project will fail, but they already fail gracefully with their own "ControlPlane edge function not found" message. Existing installs keep a harmless leftover supabase/functions/pgflow/ directory. Both deserve a line in the release notes; neither blocks removal.
title: Remove ControlPlane (pgflow edge function) — startup compilation makes it redundant
labels: enhancement, pkgs/edge-worker, pkgs/cli, pkgs/website
Summary
Drop the ControlPlane (
supabase/functions/pgflow/index.ts→ControlPlane.serve(flows)), itspgflow compileCLI command, and all supporting code/docs. Startup compilation covers everything the ControlPlane does, works reliably, and is already the documented preferred path.Docs already pre-announce this:
manual-compilation.mdxandcompile-api.mdxboth carry a deprecation notice — "Manual compilation via ControlPlane may be removed in a future release. Startup Compilation is the preferred approach."What ControlPlane actually is
ControlPlane.serve(flows)starts aDeno.serveHTTP handler exposing a single endpoint:Code:
pkgs/edge-worker/src/control-plane/(index.ts,server.ts).Exactly one consumer exists: the
pgflow compileCLI command (pkgs/cli/src/commands/compile/index.ts), which fetches SQL from the endpoint and writes a timestamped migration filesupabase/migrations/{timestamp}_create_{slug}_flow.sql.No other caller found: no CI workflows, no examples, no runtime path. Worker management (
ensure_workers()cron +track_worker_function) pings worker functions, never thepgflowfunction.deploy-first-flow.mdxalready states the ControlPlane function "is for local compilation only and is not needed in production."Why startup compilation fully covers it
FlowWorkerLifecycle.acknowledgeStart()→Queries.ensureFlowCompiled()→pgflow.ensure_flow_compiled()(pkgs/core/schemas/0100_function_ensure_flow_compiled.sql) is complete and safe:pg_advisory_xact_lock) serializes concurrent worker starts for the same flowverifiedallowDataLoss: true→ delete + recompile; production →mismatch→ worker throwsFlowShapeMismatchErrorand refuses to startThe versioned-flow workflow (
build/version-flows.mdx) also works without migrations: a versioned flow (greetUserV2) is a new slug → "missing" → compiled at startup, even in production. The only prohibited case (mutating an existing flow's shape) is blocked byensure_flow_compileditself.The get-started tutorial (quickstart, create-flow, run-flow) is 100% startup-compilation based already.
Removal checklist
pkgs/clisrc/commands/compile/and its tests (__tests__/commands/compile/,__tests__/e2e/compile.test.ts)create-edge-function.tsstep frominstall(command + its test + summary line "Create Control Plane in supabase/functions/pgflow/")README.md(compile command section)pkgs/edge-workersrc/control-plane/src/index.ts(export { ControlPlane } from './control-plane/index.js')tests/unit/control-plane/,tests/e2e/control-plane.test.tssupabase/functions/pgflow/(e2e harness);_vendor/copies shrink on next vendor syncapps/demosupabase/functions/pgflow/index.tspkgs/websiteconcepts/manual-compilation.mdxreference/control-plane-api.mdxreference/compile-api.mdx(drop CLI mentions;compileFlow()itself stays)build/version-flows.mdxstep 2: "deploy the worker — startup compilation creates the flow"deploy/supabase/deploy-first-flow.mdxreference/index.mdxpkgs/dslsrc/flow-shape.tsreferences "Used by ControlPlane"Caveats
pgflow compile. Mitigation exists and is documented:compileFlow()from@pgflow/dsl(published to npm, runs in Node). With startup compilation the schema changes at worker boot, not via reviewed migration — a philosophical regression for strict CI shops, a non-issue for everyone else. This is the only substantive trade-off.ControlPlaneis a public export of@pgflow/edge-worker(JSR + npm) — semver-major for that package. Old CLIs (pgflow@0.9–0.15 compile) run against a freshly installed project will fail, but they already fail gracefully with their own "ControlPlane edge function not found" message. Existing installs keep a harmless leftoversupabase/functions/pgflow/directory. Both deserve a line in the release notes; neither blocks removal.