<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>pgflow (Workflow Engine for Supabase) | News</title><description>A workflow engine for Postgres using Supabase queues and background tasks to process jobs in parallel. Simple and built for a great developer experience.</description><link>https://www.pgflow.dev/</link><language>en</language><item><title>pgflow 0.17.1: Private Step Queues and Anonymous Telemetry</title><link>https://www.pgflow.dev/news/pgflow-0-17-1-persistent-queues-and-telemetry/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-17-1-persistent-queues-and-telemetry/</guid><pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;0.17.0 shipped the queue identity work below; 0.17.1 adds anonymous telemetry to the same feature set. If you are upgrading from 0.16.x, this article covers the whole 0.17.x line.&lt;/p&gt;
&lt;p&gt;pgflow now persists the physical queue identity of every step and task. &lt;code dir=&quot;auto&quot;&gt;pgflow.steps&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;pgflow.step_tasks&lt;/code&gt; gain a &lt;code dir=&quot;auto&quot;&gt;queue_name&lt;/code&gt; column that stores the canonical route, snapshotted when the task is created and never rewritten. A queued task’s message identity is &lt;code dir=&quot;auto&quot;&gt;(queue_name, message_id)&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;message_id&lt;/code&gt; alone - PGMQ message ids are queue-scoped, so the same id in two different queues can no longer be mistaken for the same message. Existing flows use &lt;code dir=&quot;auto&quot;&gt;queue_mode = &apos;flow&apos;&lt;/code&gt; and retain &lt;code dir=&quot;auto&quot;&gt;lower(flow_slug)&lt;/code&gt;. Wrap a new flow with &lt;code dir=&quot;auto&quot;&gt;withStepQueues()&lt;/code&gt; to use &lt;code dir=&quot;auto&quot;&gt;queue_mode = &apos;step&apos;&lt;/code&gt;: each step receives a generated private queue.&lt;/p&gt;
&lt;p&gt;Read the &lt;a href=&quot;https://www.pgflow.dev/concepts/data-model/&quot;&gt;data model&lt;/a&gt; for what is stored, and the &lt;a href=&quot;https://www.pgflow.dev/deploy/update-pgflow/&quot;&gt;update guide&lt;/a&gt; for the full 0.16.0 → 0.17.0 procedure.&lt;/p&gt;
&lt;aside aria-label=&quot;Breaking change - matching packages and workers required&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Breaking change - matching packages and workers required &lt;/p&gt; &lt;div&gt; &lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;pgflow.start_tasks()&lt;/code&gt; now requires the &lt;code dir=&quot;auto&quot;&gt;queue_name&lt;/code&gt; argument. The released three-argument form and the NULL default are gone: the database migration drops the old overload, and &lt;code dir=&quot;auto&quot;&gt;startTasks()&lt;/code&gt; on &lt;code dir=&quot;auto&quot;&gt;IPgflowClient&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;PgflowSqlClient&lt;/code&gt; requires the queue argument in TypeScript too. The argument is the task’s &lt;strong&gt;canonical persisted route&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;lower(flow_slug)&lt;/code&gt; in flow mode or the generated step route in step mode. Step-mode direct callers also pass the exact &lt;code dir=&quot;auto&quot;&gt;step_slug&lt;/code&gt;. pgflow’s own workers poll and claim through that route, so existing flows keep working unchanged, including queues that PGMQ still lists with an older mixed-case spelling - but custom code that calls &lt;code dir=&quot;auto&quot;&gt;start_tasks()&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;startTasks()&lt;/code&gt; directly must pass the canonical route explicitly; passing the polled mixed-case spelling of an upgraded queue matches nothing.&lt;/p&gt;&lt;p&gt;There is &lt;strong&gt;no rolling mixed-version upgrade&lt;/strong&gt;. Old workers cannot claim tasks against the new schema; new workers cannot run against the old schema. Stop and drain everything, apply the migration, then deploy matching packages, workers, and explicit-queue callers together.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;what-changes&quot;&gt;What changes&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Queue identity snapshots.&lt;/strong&gt; Every step records its route in &lt;code dir=&quot;auto&quot;&gt;steps.queue_name&lt;/code&gt;; every task copies it at creation (&lt;code dir=&quot;auto&quot;&gt;step_tasks.queue_name&lt;/code&gt;). Dispatch, claims, visibility, completion, retries, skip/cancel cascades, late callbacks, stalled recovery, and pruning all address the queue through the stored snapshot.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Private step queues.&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;withStepQueues()&lt;/code&gt; derives one route for each step. Start one &lt;code dir=&quot;auto&quot;&gt;EdgeWorker&lt;/code&gt; entry point per selected &lt;code dir=&quot;auto&quot;&gt;stepSlug&lt;/code&gt;; each worker polls and claims only its own route.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Queue-scoped message identity.&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;(queue_name, message_id)&lt;/code&gt; is unique per queue where &lt;code dir=&quot;auto&quot;&gt;message_id&lt;/code&gt; is set; &lt;code dir=&quot;auto&quot;&gt;message_id&lt;/code&gt; alone stays nullable. Message ids cross the JavaScript boundary as exact decimal strings (they can exceed the safe integer range).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Provisioning safeguards.&lt;/strong&gt; Two flows can no longer address the same normalized default queue, and steps in one flow cannot differ only by case. A listed PGMQ queue with a colliding normalized name is rejected before a new flow is created, &lt;code dir=&quot;auto&quot;&gt;pgflow.flows&lt;/code&gt; is unique on &lt;code dir=&quot;auto&quot;&gt;lower(flow_slug)&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;pgflow.steps&lt;/code&gt; is unique on &lt;code dir=&quot;auto&quot;&gt;(flow_slug, lower(step_slug))&lt;/code&gt; - including direct SQL creation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Legacy mixed-case queues keep working.&lt;/strong&gt; Queues created by earlier releases keep their original pgmq spelling. PGMQ’s public message API normalizes names, so pgflow addresses them by the stored canonical name directly - no per-message queue listing. Only queue deletion resolves the original spelling through &lt;code dir=&quot;auto&quot;&gt;pgmq.list_queues()&lt;/code&gt; (PGMQ drops queue metadata by exact listed name), rejecting an ambiguous match before any destructive work; the pruning helper’s archive walk derives table names from the canonical route (&lt;code dir=&quot;auto&quot;&gt;pgmq.format_table_name()&lt;/code&gt; lowercases it).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optional pruning helper updated.&lt;/strong&gt; The manually installed &lt;code dir=&quot;auto&quot;&gt;pgflow.prune_data_older_than()&lt;/code&gt; snippet cleans messages through task snapshots and archive tables through persisted routes. Replace an installed copy; adapt customized copies yourself.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;maintenance-upgrade-from-0160&quot;&gt;Maintenance upgrade from 0.16.0&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The ordered procedure with the exact SQL lives in the &lt;a href=&quot;https://www.pgflow.dev/deploy/update-pgflow/#queue-identity-and-private-step-queues-0170&quot;&gt;update guide&lt;/a&gt;. In short: update packages and copy migrations in advance, pause new producers, gracefully drain in-flight work while the old schema is present (waiting for running handlers to finish - not for queues to empty; queued tasks and messages are retained), stop every worker including HTTP re-invocation and long-running processes, quiesce maintenance/recovery/definition writers, apply the transactional migration through Supabase’s migration runner (against the production database - &lt;code dir=&quot;auto&quot;&gt;--linked&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;--db-url&lt;/code&gt;, not the local default), replace the pruning helper if installed, deploy the matching package set, then resume maintenance, workers, and producers in that order - restoring the exact worker &lt;code dir=&quot;auto&quot;&gt;enabled&lt;/code&gt; states recorded before the window.&lt;/p&gt;
&lt;p&gt;The migration backfills existing steps and tasks with &lt;code dir=&quot;auto&quot;&gt;lower(flow_slug)&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;queue_mode = &apos;flow&apos;&lt;/code&gt; - including tasks whose &lt;code dir=&quot;auto&quot;&gt;message_id&lt;/code&gt; is NULL - and fails atomically on conflicting data (flows differing only by slug case, case-only duplicate step slugs, invalid leading or trailing underscore or &lt;code dir=&quot;auto&quot;&gt;__&lt;/code&gt; slugs, duplicate &lt;code dir=&quot;auto&quot;&gt;(queue_name, message_id)&lt;/code&gt; pairs, queue names beyond PGMQ’s 47-character limit). A failed migration leaves the database unchanged; resolve conflicts manually and re-run it. After a successful migration, old workers cannot simply restart. No queues or messages are migrated or recreated, and flow slug casing is untouched.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;anonymous-telemetry&quot;&gt;Anonymous telemetry&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;pgflow now includes anonymous, opt-out usage telemetry so development can be guided by real usage instead of guesses. Once per day your database summarizes yesterday’s activity into coarse buckets - active or not, versions running, run and worker counts, flow shapes, feature adoption - and sends one small JSON document. Nothing identifying ever leaves your database: no slugs, names, IDs, inputs, outputs, errors, or addresses.&lt;/p&gt;
&lt;p&gt;You can inspect the exact bytes of every past report with &lt;code dir=&quot;auto&quot;&gt;select * from pgflow_telemetry.sent_reports&lt;/code&gt;, preview any day with &lt;code dir=&quot;auto&quot;&gt;pgflow_telemetry.preview()&lt;/code&gt;, and disable it permanently with one line:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow_telemetry&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;disable&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Read the full details - what is collected, what is never collected, where data lives and for how long - in the &lt;a href=&quot;https://www.pgflow.dev/reference/telemetry/&quot;&gt;telemetry reference&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>release</category><category>breaking</category></item><item><title>pgflow 0.16.0: Startup-Only Flow Compilation</title><link>https://www.pgflow.dev/news/pgflow-0-16-0-startup-only-flow-compilation/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-16-0-startup-only-flow-compilation/</guid><pubDate>Mon, 07 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This release makes worker startup the only supported way to deploy a flow. Every flow worker compiles or verifies its imported definition in the database before it registers itself and starts polling. A failed compilation registers nothing — no worker function is tracked, no worker row appears, and existing registrations stay untouched.&lt;/p&gt;
&lt;p&gt;Read &lt;a href=&quot;https://www.pgflow.dev/concepts/startup-compilation/&quot;&gt;Startup Compilation&lt;/a&gt; for how deployment works now, and &lt;a href=&quot;https://www.pgflow.dev/build/version-flows/&quot;&gt;Versioning Flows&lt;/a&gt; for when a flow needs a new slug.&lt;/p&gt;
&lt;aside aria-label=&quot;Breaking change — check your project before upgrading&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Breaking change — check your project before upgrading &lt;/p&gt; &lt;div&gt; &lt;p&gt;This release removes features that existing projects may still use:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;the &lt;code dir=&quot;auto&quot;&gt;pgflow compile&lt;/code&gt; command and scripts or CI jobs that call it;&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;compileFlow()&lt;/code&gt; and migration-based flow deployment;&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;compareFlowShapes()&lt;/code&gt; from &lt;code dir=&quot;auto&quot;&gt;@pgflow/dsl&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;ControlPlane, including the &lt;code dir=&quot;auto&quot;&gt;ControlPlane&lt;/code&gt; export, deployed &lt;code dir=&quot;auto&quot;&gt;supabase/functions/pgflow&lt;/code&gt;, and its &lt;code dir=&quot;auto&quot;&gt;[functions.pgflow]&lt;/code&gt; configuration;&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;FlowWorkerConfig.compilation&lt;/code&gt;, including &lt;code dir=&quot;auto&quot;&gt;compilation: false&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;allowDataLoss&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;pgflow.ensure_flow_compiled(text, jsonb, boolean)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Do not apply the database migration while old workers are running.&lt;/strong&gt; Stop and drain them first, update all pgflow packages and worker code together, remove the legacy configuration, apply the migration, then deploy the new workers. Old workers cannot start after the migration.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;what-is-removed&quot;&gt;What is removed&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;compileFlow()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;compareFlowShapes()&lt;/code&gt; from &lt;code dir=&quot;auto&quot;&gt;@pgflow/dsl&lt;/code&gt; — SQL text generation and the TypeScript comparator are gone. Shape comparison lives only in PostgreSQL (&lt;code dir=&quot;auto&quot;&gt;_compare_flow_shapes()&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;ControlPlane — the HTTP SQL-compiler edge function, its export from &lt;code dir=&quot;auto&quot;&gt;@pgflow/edge-worker&lt;/code&gt;, and the &lt;code dir=&quot;auto&quot;&gt;supabase/functions/pgflow/&lt;/code&gt; folder the installer used to create.&lt;/li&gt;
&lt;li&gt;The &lt;code dir=&quot;auto&quot;&gt;pgflow compile&lt;/code&gt; CLI command.&lt;/li&gt;
&lt;li&gt;The &lt;code dir=&quot;auto&quot;&gt;FlowWorkerConfig.compilation&lt;/code&gt; option in all its forms (&lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;{}&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;{ allowDataLoss: true }&lt;/code&gt;). Stale properties in already-deployed JavaScript are ignored.&lt;/li&gt;
&lt;li&gt;The production data-loss path: &lt;code dir=&quot;auto&quot;&gt;pgflow.ensure_flow_compiled(text, jsonb, boolean)&lt;/code&gt;. The database migration drops this overload, so production can no longer authorize destructive recompilation. Local development keeps automatic destructive recompilation for same-slug mismatches (hot reload).&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;upgrading-http-worker-functions&quot;&gt;Upgrading HTTP worker functions&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For each HTTP worker function:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Record its exact &lt;code dir=&quot;auto&quot;&gt;worker_functions.enabled&lt;/code&gt; value.&lt;/li&gt;
&lt;li&gt;Set &lt;code dir=&quot;auto&quot;&gt;enabled = false&lt;/code&gt;, deprecate its workers, and wait for heartbeats and in-flight tasks to drain by following &lt;a href=&quot;https://www.pgflow.dev/deploy/supabase/update-deployed-flows/&quot;&gt;Update Deployed Flows&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Update &lt;code dir=&quot;auto&quot;&gt;pgflow&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;@pgflow/core&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;@pgflow/dsl&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;@pgflow/client&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;@pgflow/edge-worker&lt;/code&gt; to the same version.&lt;/li&gt;
&lt;li&gt;Run &lt;code dir=&quot;auto&quot;&gt;npx pgflow@latest install&lt;/code&gt;, review the copied migration, and apply it while old workers remain stopped.&lt;/li&gt;
&lt;li&gt;Deploy workers that import their complete flow definitions.&lt;/li&gt;
&lt;li&gt;Restore each recorded &lt;code dir=&quot;auto&quot;&gt;enabled&lt;/code&gt; value and check a fresh heartbeat.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;upgrading-process-workers&quot;&gt;Upgrading process workers&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Stop the processes and external supervisors before applying the migration. Update the packages and database, then restart the supervisors.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;remove-legacy-project-files-and-configuration&quot;&gt;Remove legacy project files and configuration&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;rm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-rf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;supabase/functions/pgflow&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;supabase@latest&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;functions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--project-ref&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;your-project-ref&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;your-project-ref&lt;/code&gt; is your Supabase project reference. The remote delete command is required only when the ControlPlane function was deployed.&lt;/p&gt;
&lt;p&gt;Also remove any &lt;code dir=&quot;auto&quot;&gt;[functions.pgflow]&lt;/code&gt; block from &lt;code dir=&quot;auto&quot;&gt;supabase/config.toml&lt;/code&gt;, every &lt;code dir=&quot;auto&quot;&gt;pgflow compile&lt;/code&gt; script or CI step, and every worker &lt;code dir=&quot;auto&quot;&gt;compilation&lt;/code&gt; property. Keep existing generated flow migration files as immutable migration history — do not delete or rewrite migrations that a database already applied.&lt;/p&gt;</content:encoded><category>release</category><category>breaking</category></item><item><title>pgflow 0.15.1: Reliable Task Finalization and Recovery</title><link>https://www.pgflow.dev/news/pgflow-0-15-1-task-lifecycle-hardening/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-15-1-task-lifecycle-hardening/</guid><pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This patch release hardens the task lifecycle. Tasks now reach a terminal state on every completion path, stalled-task recovery uses the right timeout, claimed tasks keep their queue visibility before handlers run, and &lt;code dir=&quot;auto&quot;&gt;npm install pgflow&lt;/code&gt; works again on Windows.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;tasks-under-skipped-steps&quot;&gt;Tasks Under Skipped Steps&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;When a step was skipped via &lt;code dir=&quot;auto&quot;&gt;whenExhausted: &apos;skip&apos;&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;&apos;skip-cascade&apos;&lt;/code&gt; (or skipped by a cascade), sibling task rows stayed &lt;code dir=&quot;auto&quot;&gt;queued&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;started&lt;/code&gt; forever. The step was skipped, but its task rows never ended. This was reported in &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/638&quot;&gt;#638&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Task rows under a skipped step are now terminalized as &lt;code dir=&quot;auto&quot;&gt;skipped&lt;/code&gt;. Two ordering details make this safe:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tasks are terminalized before their queue messages are archived, preserving the task-before-queue lock order.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;start_tasks&lt;/code&gt; only returns rows it actually claimed, so workers no longer execute tasks that a concurrent skip already marked &lt;code dir=&quot;auto&quot;&gt;skipped&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;tasks-on-failed-runs&quot;&gt;Tasks on Failed Runs&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;When a run failed, unfinished task rows on that run stayed active. A late step callback or the stalled-task recovery job could then “finish” a task after its run had already failed. This was reported in &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/645&quot;&gt;#645&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unfinished tasks are now marked &lt;code dir=&quot;auto&quot;&gt;cancelled&lt;/code&gt; when their run fails, and late callbacks and stalled recovery can no longer revive them.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;stalled-task-recovery-uses-the-step-timeout&quot;&gt;Stalled-Task Recovery Uses the Step Timeout&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Stalled tasks were requeued only after their &lt;em&gt;flow&lt;/em&gt; timeout expired, so recovery for a short step inside a long flow waited far longer than necessary. This was reported in &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/621&quot;&gt;#621&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Requeue now uses the effective step timeout: the step timeout when set, otherwise the flow timeout.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;claim-visibility-before-handlers-run&quot;&gt;Claim Visibility Before Handlers Run&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;start_tasks()&lt;/code&gt; claimed tasks but applied the PGMQ visibility extension in a way PostgreSQL could skip, so a claimed task sometimes kept only the initial read visibility. A handler that ran longer than that window made the queue message visible again, so a second worker could pick up the same task. This was reported in &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/656&quot;&gt;#656&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The visibility update is now structurally required (a referenced CTE instead of an unreferenced &lt;code dir=&quot;auto&quot;&gt;SELECT&lt;/code&gt; CTE), so every claimed task keeps the effective timeout (&lt;code dir=&quot;auto&quot;&gt;coalesce(step timeout, flow timeout) + 2&lt;/code&gt;) before handlers run, and a visibility-update failure rolls back the whole claim.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;windows-install-fixed&quot;&gt;Windows Install Fixed&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The CLI package’s postinstall script ran &lt;code dir=&quot;auto&quot;&gt;chmod&lt;/code&gt; on its bin file, which broke &lt;code dir=&quot;auto&quot;&gt;npm install pgflow&lt;/code&gt; on Windows. This was reported in &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/610&quot;&gt;#610&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The postinstall script is gone. npm sets the executable bit for &lt;code dir=&quot;auto&quot;&gt;bin&lt;/code&gt; files automatically, so a plain &lt;code dir=&quot;auto&quot;&gt;npm install pgflow&lt;/code&gt; works on Windows again.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;automatic-repair-of-existing-data&quot;&gt;Automatic Repair of Existing Data&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The single consolidated migration &lt;code dir=&quot;auto&quot;&gt;20260904095427_pgflow_task_lifecycle_hardening&lt;/code&gt; repairs existing task rows in the same order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Active task rows (&lt;code dir=&quot;auto&quot;&gt;queued&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;started&lt;/code&gt;) under skipped steps become &lt;code dir=&quot;auto&quot;&gt;skipped&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Remaining active task rows on failed runs become &lt;code dir=&quot;auto&quot;&gt;cancelled&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Completed and genuinely failed tasks keep their outcomes, and all history fields are preserved. No manual action is required.&lt;/p&gt;
&lt;p&gt;To pick up these fixes, follow &lt;a href=&quot;https://www.pgflow.dev/deploy/update-pgflow/&quot;&gt;Update pgflow&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>bugfix</category><category>patch</category></item><item><title>pgflow 0.15.0: Standalone Workers with Node and Bun</title><link>https://www.pgflow.dev/news/pgflow-0-15-0-node-bun-workers/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-15-0-node-bun-workers/</guid><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;pgflow workers are no longer tied to Supabase Edge Functions. This release publishes &lt;code dir=&quot;auto&quot;&gt;@pgflow/edge-worker&lt;/code&gt; to npm and adds a process runtime that runs workers as long-lived Node or Bun processes — on Railway, Fly.io, Docker, or any VM.&lt;/p&gt;
&lt;aside aria-label=&quot;Supabase is still required&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Supabase is still required &lt;/p&gt; &lt;div&gt; &lt;p&gt;Flows, runs, and task queues still live in your Supabase Postgres database — only the worker &lt;em&gt;process&lt;/em&gt; moved. It runs on your infrastructure and connects back to Supabase. Edge Function workers keep working as before.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;run-a-worker-with-node-or-bun&quot;&gt;Run a worker with Node or Bun&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Install the package with your package manager of choice, set your connection variables, and start a worker script:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@pgflow/edge-worker&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;pnpm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@pgflow/edge-worker&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;bun&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@pgflow/edge-worker&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;worker.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { EdgeWorker } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;@pgflow/edge-worker&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { ProcessOrders } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;./flows/process-orders.js&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; EdgeWorker&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt;(ProcessOrders);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Process workers handle &lt;code dir=&quot;auto&quot;&gt;SIGTERM&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;SIGINT&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;SIGQUIT&lt;/code&gt; with graceful drain: tasks finish, the worker is marked stopped, and connections close before exit.&lt;/p&gt;
&lt;p&gt;See the &lt;a href=&quot;https://www.pgflow.dev/deploy/node-bun-process-workers/&quot;&gt;Node/Bun Process Workers guide&lt;/a&gt; for deployment recipes and configuration.&lt;/p&gt;
&lt;p&gt;Already using pgflow? 0.15.0 ships a database migration — follow &lt;a href=&quot;https://www.pgflow.dev/deploy/update-pgflow/&quot;&gt;Update pgflow&lt;/a&gt; before deploying process workers.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;supabase-edge-function-improvements&quot;&gt;Supabase Edge Function improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Edge Function workers also got lifecycle hardening in this release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bounded shutdown.&lt;/strong&gt; Shutdown finishes within a five-second deadline; PostgreSQL connections are force-closed if it expires.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Serialized startup.&lt;/strong&gt; Concurrent requests share one startup; none observe a half-started worker.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Retry backoff.&lt;/strong&gt; Persistent database failures back off exponentially (100 ms to 5 s) instead of hot-looping.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>feature</category><category>minor</category></item><item><title>pgflow 0.14.0: Conditional Step Execution</title><link>https://www.pgflow.dev/news/pgflow-0-14-0-conditional-step-execution/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-14-0-conditional-step-execution/</guid><pubDate>Wed, 18 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;pgflow 0.14.0 introduces conditional step execution - run steps based on input patterns and handle failures gracefully without failing the entire workflow.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;highlights&quot;&gt;Highlights&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;if&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;ifNot&lt;/code&gt;&lt;/strong&gt; - Skip steps based on JSON containment patterns&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;whenUnmet&lt;/code&gt;&lt;/strong&gt; - Control behavior when conditions aren’t met (&lt;code dir=&quot;auto&quot;&gt;fail&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;skip&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;skip-cascade&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;whenExhausted&lt;/code&gt;&lt;/strong&gt; - Handle step failures gracefully after all retries fail&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type-safe&lt;/strong&gt; - TypeScript tracks which dependencies may be &lt;code dir=&quot;auto&quot;&gt;undefined&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;pattern-matching-with-if--ifnot&quot;&gt;Pattern Matching with &lt;code dir=&quot;auto&quot;&gt;if&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;ifNot&lt;/code&gt;&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Use &lt;code dir=&quot;auto&quot;&gt;if&lt;/code&gt; to run a step only when input contains a pattern:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;premiumFeature&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;if: { plan: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;premium&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;whenUnmet: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;skip&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}, handler)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Use &lt;code dir=&quot;auto&quot;&gt;ifNot&lt;/code&gt; to run a step only when input does NOT contain a pattern:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;trialReminder&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ifNot: { plan: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;premium&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;whenUnmet: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;skip&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}, handler)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;json-containment-semantics&quot;&gt;JSON Containment Semantics&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Patterns use PostgreSQL’s &lt;code dir=&quot;auto&quot;&gt;@&gt;&lt;/code&gt; containment operator. Your pattern only needs the fields you care about:&lt;/p&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Input&lt;/th&gt;&lt;th&gt;Pattern&lt;/th&gt;&lt;th&gt;Match?&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;{ plan: &apos;premium&apos;, name: &apos;Alice&apos; }&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;{ plan: &apos;premium&apos; }&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;{ plan: &apos;free&apos; }&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;{ plan: &apos;premium&apos; }&lt;/code&gt;&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;{ user: { role: &apos;admin&apos;, name: &apos;Bob&apos; } }&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;{ user: { role: &apos;admin&apos; } }&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;{ tags: [&apos;urgent&apos;, &apos;support&apos;] }&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;{ tags: [&apos;urgent&apos;] }&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;aside aria-label=&quot;Tip&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Tip &lt;/p&gt; &lt;div&gt; &lt;p&gt;For root steps, patterns match against flow input. For dependent steps, patterns match against &lt;code dir=&quot;auto&quot;&gt;{ depSlug: depOutput, ... }&lt;/code&gt;.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;p&gt;See &lt;a href=&quot;https://www.pgflow.dev/build/conditional-steps/pattern-matching/&quot;&gt;Pattern Matching&lt;/a&gt; for complete semantics.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;behavior-modes&quot;&gt;Behavior Modes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;whenUnmet&lt;/code&gt; option controls what happens when a condition isn’t met:&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Mode&lt;/th&gt;&lt;th&gt;Step&lt;/th&gt;&lt;th&gt;Dependents&lt;/th&gt;&lt;th&gt;Run&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;fail&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Fails&lt;/td&gt;&lt;td&gt;Not executed&lt;/td&gt;&lt;td&gt;Fails&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;skip&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Skipped&lt;/td&gt;&lt;td&gt;Receive &lt;code dir=&quot;auto&quot;&gt;undefined&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Continues&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;skip-cascade&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Skipped&lt;/td&gt;&lt;td&gt;All skipped&lt;/td&gt;&lt;td&gt;Continues&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Skip entire feature branch if condition not met&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;loadPremiumData&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;if: { plan: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;premium&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;whenUnmet: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;skip-cascade&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}, handler)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;See &lt;a href=&quot;https://www.pgflow.dev/build/conditional-steps/skip-modes/&quot;&gt;Skip Modes&lt;/a&gt; for detailed guidance on choosing modes.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;graceful-failure-handling&quot;&gt;Graceful Failure Handling&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;code dir=&quot;auto&quot;&gt;whenExhausted&lt;/code&gt; option controls what happens after all retries fail:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;sendWelcomeEmail&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dependsOn: [&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;createAccount&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;maxAttempts: &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;whenExhausted: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;skip&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,  &lt;/span&gt;&lt;span&gt;// Continue even if email fails&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}, handler)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Use &lt;code dir=&quot;auto&quot;&gt;whenExhausted: &apos;skip&apos;&lt;/code&gt; for non-critical steps like notifications, analytics, or enrichment that shouldn’t block the main workflow.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&quot;https://www.pgflow.dev/build/graceful-failure/&quot;&gt;Graceful Failure&lt;/a&gt; for patterns.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;type-safety&quot;&gt;Type Safety&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;pgflow’s type system tracks which steps may be skipped:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;processResults&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dependsOn: [&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;optionalEnrichment&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}, &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// TypeScript knows this may be undefined&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;optionalEnrichment&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;processWithEnrichment&lt;/span&gt;&lt;span&gt;(input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;optionalEnrichment&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;processBasic&lt;/span&gt;&lt;span&gt;(input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;With &lt;code dir=&quot;auto&quot;&gt;skip-cascade&lt;/code&gt;, dependent types remain required - if the step runs, the dependency is guaranteed.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;migration&quot;&gt;Migration&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release includes schema changes. After upgrading, run:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow@latest&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Then apply the new migration:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;supabase&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;db&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside aria-label=&quot;Caution&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Caution &lt;/p&gt; &lt;div&gt; &lt;p&gt;The migration adds new columns (&lt;code dir=&quot;auto&quot;&gt;required_input_pattern&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;forbidden_input_pattern&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;when_unmet&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;when_exhausted&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;skip_reason&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;skipped_at&lt;/code&gt;) and a new step status (&lt;code dir=&quot;auto&quot;&gt;skipped&lt;/code&gt;). Existing flows continue to
work unchanged.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;p&gt;See &lt;a href=&quot;https://www.pgflow.dev/get-started/installation/&quot;&gt;Install pgflow&lt;/a&gt; for upgrade details.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;learn-more&quot;&gt;Learn More&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/build/conditional-steps/&quot;&gt;Conditional Steps Overview&lt;/a&gt; - Introduction to the feature&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/build/conditional-steps/pattern-matching/&quot;&gt;Pattern Matching&lt;/a&gt; - JSON containment patterns&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/build/conditional-steps/skip-modes/&quot;&gt;Skip Modes&lt;/a&gt; - Detailed mode comparison&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/build/graceful-failure/&quot;&gt;Graceful Failure&lt;/a&gt; - Handling failures with &lt;code dir=&quot;auto&quot;&gt;whenExhausted&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/build/conditional-steps/examples/&quot;&gt;Examples&lt;/a&gt; - AI/LLM patterns like query routing and RAG fallback&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>release</category><category>dsl</category><category>conditional-execution</category></item><item><title>pgflow 0.13.3: Authentication Fix for ensure_workers and EdgeWorker</title><link>https://www.pgflow.dev/news/pgflow-0-13-3-authentication-fix-for-ensure-workers-and-edge-worker/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-13-3-authentication-fix-for-ensure-workers-and-edge-worker/</guid><pubDate>Tue, 03 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This release fixes a critical authentication issue where &lt;code dir=&quot;auto&quot;&gt;ensure_workers()&lt;/code&gt; fails to start Edge Workers due to key format mismatches, resulting in 401 Unauthorized errors. This resolves &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/603&quot;&gt;GitHub issue #603&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Supabase stores the service role key in different formats depending on where you access it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;In Vault&lt;/strong&gt; (used by &lt;code dir=&quot;auto&quot;&gt;ensure_workers&lt;/code&gt;): JWT format starting with &lt;code dir=&quot;auto&quot;&gt;eyJhbG...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In Edge Functions&lt;/strong&gt; (&lt;code dir=&quot;auto&quot;&gt;SUPABASE_SERVICE_ROLE_KEY&lt;/code&gt; env var): Internal format starting with &lt;code dir=&quot;auto&quot;&gt;sb_secret_...&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When &lt;code dir=&quot;auto&quot;&gt;ensure_workers&lt;/code&gt; sends an HTTP request to trigger a worker, it includes the JWT-format key from vault in the Authorization header. However, the Edge Worker validates this against &lt;code dir=&quot;auto&quot;&gt;SUPABASE_SERVICE_ROLE_KEY&lt;/code&gt;, which contains the &lt;code dir=&quot;auto&quot;&gt;sb_secret_...&lt;/code&gt; format. Since these strings don’t match, authentication fails with a 401 error.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-solution&quot;&gt;The Solution&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We’ve introduced &lt;code dir=&quot;auto&quot;&gt;PGFLOW_AUTH_SECRET&lt;/code&gt; - a user-controlled authentication secret that bypasses the format mismatch entirely:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Store your custom secret in vault as &lt;code dir=&quot;auto&quot;&gt;pgflow_auth_secret&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set the same value as &lt;code dir=&quot;auto&quot;&gt;PGFLOW_AUTH_SECRET&lt;/code&gt; in your Edge Function secrets&lt;/li&gt;
&lt;li&gt;Both sides now use the identical string for authentication&lt;/li&gt;
&lt;/ol&gt;
&lt;aside aria-label=&quot;Set the same value in both locations&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Set the same value in both locations &lt;/p&gt; &lt;div&gt; &lt;p&gt;You must set the same secret value in both vault and Edge Functions. Since
Supabase uses different key formats internally, relying on the fallback can
cause authentication failures. Always set both &lt;code dir=&quot;auto&quot;&gt;pgflow_auth_secret&lt;/code&gt; in vault
and &lt;code dir=&quot;auto&quot;&gt;PGFLOW_AUTH_SECRET&lt;/code&gt; in Edge Functions to the same value.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;how-to-update&quot;&gt;How to Update&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Update your pgflow installation and configure the new authentication secret:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Update your packages and migrations following the &lt;a href=&quot;https://www.pgflow.dev/deploy/update-pgflow/&quot;&gt;update guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Set &lt;code dir=&quot;auto&quot;&gt;pgflow_auth_secret&lt;/code&gt; in vault (same value you’ll use in step 3):
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vault&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;create_secret&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;your-secret-value&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;pgflow_auth_secret&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Set &lt;code dir=&quot;auto&quot;&gt;PGFLOW_AUTH_SECRET&lt;/code&gt; in your Edge Function secrets with the same value&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;See the &lt;a href=&quot;https://www.pgflow.dev/deploy/supabase/configure-secrets/&quot;&gt;Configure Secrets&lt;/a&gt; documentation for detailed setup instructions.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;backward-compatibility&quot;&gt;Backward Compatibility&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For backwards compatibility, pgflow falls back to the legacy secrets if &lt;code dir=&quot;auto&quot;&gt;PGFLOW_AUTH_SECRET&lt;/code&gt; is not configured:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Database side&lt;/strong&gt;: Falls back to &lt;code dir=&quot;auto&quot;&gt;supabase_service_role_key&lt;/code&gt; in vault&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Edge Function side&lt;/strong&gt;: Falls back to &lt;code dir=&quot;auto&quot;&gt;SUPABASE_SERVICE_ROLE_KEY&lt;/code&gt; env var&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Existing deployments will continue to work without immediate changes, though we strongly recommend migrating to &lt;code dir=&quot;auto&quot;&gt;PGFLOW_AUTH_SECRET&lt;/code&gt; to avoid the format mismatch issues.&lt;/p&gt;</content:encoded><category>bugfix</category><category>authentication</category><category>edge-worker</category><category>release</category></item><item><title>pgflow 0.13.2: Stalled Task Recovery and Config Fixes</title><link>https://www.pgflow.dev/news/pgflow-0-13-2-stalled-task-recovery-and-config-fixes/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-13-2-stalled-task-recovery-and-config-fixes/</guid><pubDate>Mon, 12 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This patch release fixes two issues: tasks getting stuck when workers crash, and the &lt;code dir=&quot;auto&quot;&gt;maxPgConnections&lt;/code&gt; config being ignored.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;stalled-tasks-automatic-recovery&quot;&gt;Stalled Tasks Automatic Recovery&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;the-problem&quot;&gt;The Problem&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;When a worker crashes or is terminated unexpectedly, tasks can get stuck in &lt;code dir=&quot;auto&quot;&gt;started&lt;/code&gt; status indefinitely. These “stalled” tasks never complete and block flow progress. This was reported in &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/586&quot;&gt;#586&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;the-solution&quot;&gt;The Solution&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;A new &lt;code dir=&quot;auto&quot;&gt;pgflow.requeue_stalled_tasks()&lt;/code&gt; function automatically detects and recovers stalled tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Runs via cron job every 15 seconds&lt;/li&gt;
&lt;li&gt;Identifies tasks stuck in &lt;code dir=&quot;auto&quot;&gt;started&lt;/code&gt; status beyond their timeout + 30s buffer&lt;/li&gt;
&lt;li&gt;Requeues them back to &lt;code dir=&quot;auto&quot;&gt;queued&lt;/code&gt; status (up to 3 times)&lt;/li&gt;
&lt;li&gt;After 3 requeue attempts, archives the message and marks task with &lt;code dir=&quot;auto&quot;&gt;permanently_stalled_at&lt;/code&gt; timestamp for manual investigation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The cron job is set up automatically via migration. For more details, see the &lt;a href=&quot;https://www.pgflow.dev/deploy/troubleshooting-stalled-tasks/&quot;&gt;Troubleshooting Stalled Tasks&lt;/a&gt; guide.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;visibility-timeout-increase&quot;&gt;Visibility Timeout Increase&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Default visibility timeout increased from 2s to 5s to reduce the likelihood of tasks appearing stalled during normal processing delays.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;did-this-affect-you&quot;&gt;Did This Affect You?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Run this query to check if you had stalled tasks before upgrading:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step_tasks&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;started&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;AND&lt;/span&gt;&lt;span&gt; started_at &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;now&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; interval &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;5 minutes&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;If you see results, those tasks will now be automatically recovered.&lt;/p&gt;
&lt;p&gt;To find tasks that exceeded the max requeue limit (for manual investigation):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;run_id&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;flow_slug&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;st&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step_slug&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;st&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;requeued_count&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;st&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;permanently_stalled_at&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step_tasks&lt;/span&gt;&lt;span&gt; st&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;JOIN&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;runs&lt;/span&gt;&lt;span&gt; r &lt;/span&gt;&lt;span&gt;ON&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;run_id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;st&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;run_id&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;st&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;permanently_stalled_at&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;IS NOT NULL&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;connection-config-fix&quot;&gt;Connection Config Fix&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;the-bug&quot;&gt;The Bug&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;maxPgConnections&lt;/code&gt; configuration option was being ignored when passed to &lt;code dir=&quot;auto&quot;&gt;createFlowWorker()&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;the-fix&quot;&gt;The Fix&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The config is now properly passed through the connection chain with a default of 4 connections.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;credits&quot;&gt;Credits&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://github.com/matz&quot;&gt;matz&lt;/a&gt; for reporting issue &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/586&quot;&gt;#586&lt;/a&gt;!&lt;/p&gt;</content:encoded><category>bugfix</category><category>patch</category></item><item><title>pgflow 0.13.1: CLI Fix + Step Output Storage for Conditional Execution</title><link>https://www.pgflow.dev/news/pgflow-0-13-1-cli-fix-step-output-storage-for-conditional-execution/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-13-1-cli-fix-step-output-storage-for-conditional-execution/</guid><pubDate>Sat, 03 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;aside aria-label=&quot;Note on 0.13.0&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Note on 0.13.0 &lt;/p&gt; &lt;div&gt; &lt;p&gt;Version 0.13.0 was yanked from npm and JSR due to unreliable local environment detection. The key-based detection approach did not work correctly with recent Supabase CLI versions. This release (0.13.1) replaces it with a more robust URL-based detection method.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;p&gt;pgflow 0.13.1 fixes a compatibility issue with recent Supabase CLI versions and introduces atomic step output storage for 2x faster Map chains.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;supabase-cli-compatibility-fix&quot;&gt;Supabase CLI Compatibility Fix&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;If local development stopped working after a Supabase CLI update, this release fixes it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;pgflow now detects local development by checking the &lt;code dir=&quot;auto&quot;&gt;SUPABASE_URL&lt;/code&gt; environment variable. When running locally, Supabase CLI sets this to &lt;code dir=&quot;auto&quot;&gt;http://kong:8000&lt;/code&gt; (the Docker-internal API gateway). This is more reliable than the previous key-based detection, which broke when Supabase CLI transitioned to new opaque API keys.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;step-output-storage&quot;&gt;Step Output Storage&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;what-changed&quot;&gt;What Changed&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Step outputs are now stored in &lt;code dir=&quot;auto&quot;&gt;step_states.output&lt;/code&gt; when a step completes, rather than being aggregated on-demand.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;how-it-worked-before&quot;&gt;How It Worked Before&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Previously, every time a downstream step needed its dependency’s output, pgflow ran an aggregation query:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; jsonb_agg(&lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ORDER BY&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;index&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step_tasks&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; run_id &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; $&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;AND&lt;/span&gt;&lt;span&gt; step_slug &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; $&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;For a Map step with 500 items, this query scanned 500 rows. When another Map step depended on it with 500 tasks, that’s 500 tasks x 500 rows = 250,000 row scans.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;performance-gains&quot;&gt;Performance Gains&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;With outputs pre-stored, downstream tasks now read a single column instead of aggregating:&lt;/p&gt;

















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Benchmark&lt;/th&gt;&lt;th&gt;Before&lt;/th&gt;&lt;th&gt;After&lt;/th&gt;&lt;th&gt;Improvement&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Start 500 tasks reading 500-element output&lt;/td&gt;&lt;td&gt;189s&lt;/td&gt;&lt;td&gt;87s&lt;/td&gt;&lt;td&gt;&lt;strong&gt;2.17x faster&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The complexity dropped from O(N^2) to O(N) for Map-to-Map chains.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;simpler-manual-queries&quot;&gt;Simpler Manual Queries&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Querying step outputs is now straightforward:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;-- Get output for a specific step in a run&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step_states&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; run_id &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;run-abc&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;AND&lt;/span&gt;&lt;span&gt; step_slug &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;-- Get all step outputs for a run&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; step_slug, &lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step_states&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; run_id &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;run-abc&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;No need to aggregate from &lt;code dir=&quot;auto&quot;&gt;step_tasks&lt;/code&gt; - the output is ready to use.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;migration-guide&quot;&gt;Migration Guide&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release includes a data migration that backfills &lt;code dir=&quot;auto&quot;&gt;step_states.output&lt;/code&gt; for existing completed steps.&lt;/p&gt;
&lt;aside aria-label=&quot;Data Migration - Test First&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Data Migration - Test First &lt;/p&gt; &lt;div&gt; &lt;p&gt;This migration backfills data for all completed steps. Download a production database dump and test the migration locally before applying to production. The backfill is safe (only touches completed rows) but should run during low-traffic periods and with no workers running.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;ol role=&quot;list&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Test locally with production data&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Download a production backup and restore it locally to test the migration. See &lt;a href=&quot;https://supabase.com/docs/guides/local-development/restoring-downloaded-backup/&quot;&gt;Restoring a downloaded backup&lt;/a&gt; in the Supabase docs, then run &lt;code dir=&quot;auto&quot;&gt;npx supabase db push&lt;/code&gt; to test the migration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Record enabled worker functions&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Before disabling, note which functions are currently enabled:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; function_name &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;worker_functions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enabled&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; true;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Save this list - you’ll need it in step 7.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Disable all worker functions&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;UPDATE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;worker_functions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SET&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enabled&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; false;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deprecate running workers&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;UPDATE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;workers&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SET&lt;/span&gt;&lt;span&gt; deprecated_at &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NOW&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; deprecated_at &lt;/span&gt;&lt;span&gt;IS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;AND&lt;/span&gt;&lt;span&gt; stopped_at &lt;/span&gt;&lt;span&gt;IS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wait for all workers to stop&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;COUNT&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;workers&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; stopped_at &lt;/span&gt;&lt;span&gt;IS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Wait until this returns &lt;code dir=&quot;auto&quot;&gt;0&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Apply database migration&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;supabase&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;db&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deploy workers and re-enable&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Deploy your workers and re-enable only the functions that were enabled before:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;supabase&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;functions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deploy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;UPDATE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;worker_functions&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SET&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enabled&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; function_name &lt;/span&gt;&lt;span&gt;IN&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;worker-1&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;worker-2&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;);  &lt;/span&gt;&lt;span&gt;-- from step 2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;looking-ahead&quot;&gt;Looking Ahead&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This change stores step outputs in a queryable location - a prerequisite for conditional execution. Future releases will use these stored outputs to evaluate conditions and skip steps dynamically.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Questions or issues? Join the &lt;a href=&quot;https://discord.gg/pgflow&quot;&gt;Discord community&lt;/a&gt; or &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues&quot;&gt;open a GitHub issue&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>release</category><category>performance</category></item><item><title>pgflow 0.12.0: Simpler Handler Signatures for Flow Composition</title><link>https://www.pgflow.dev/news/pgflow-0-12-0-simpler-handler-signatures-for-flow-composition/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-12-0-simpler-handler-signatures-for-flow-composition/</guid><pubDate>Wed, 24 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;pgflow 0.12.0 introduces asymmetric handler signatures - a breaking change that removes the &lt;code dir=&quot;auto&quot;&gt;run&lt;/code&gt; wrapper from step inputs, enabling cleaner functional composition and preparing the foundation for subflows.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-changed&quot;&gt;What Changed&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Handler signatures are now &lt;strong&gt;asymmetric&lt;/strong&gt;. The &lt;code dir=&quot;auto&quot;&gt;input.run&lt;/code&gt; pattern no longer exists.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Root steps&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(&lt;/span&gt;&lt;del&gt;&lt;span&gt;input&lt;/span&gt;&lt;/del&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;del&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;/del&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;xxx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(&lt;/span&gt;&lt;ins&gt;&lt;span&gt;flowInput&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;ins&gt;&lt;span&gt;flowInput&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;xxx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Dependent steps&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(&lt;/span&gt;&lt;del&gt;&lt;span&gt;input&lt;/span&gt;&lt;/del&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;del&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;dep&lt;/span&gt;&lt;/del&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;xxx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(&lt;/span&gt;&lt;ins&gt;&lt;span&gt;deps&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;ins&gt;&lt;span&gt;deps&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;dep&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;xxx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Dependent needing &lt;/span&gt;&lt;ins&gt;&lt;span&gt;flowInput&lt;/span&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(&lt;/span&gt;&lt;del&gt;&lt;span&gt;input&lt;/span&gt;&lt;/del&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;del&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;/del&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;xxx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;ins&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/ins&gt;&lt;span&gt;(&lt;/span&gt;&lt;ins&gt;&lt;span&gt;&lt;span&gt;deps&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;ins&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; ctx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;flowInput&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;xxx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside aria-label=&quot;Breaking Change&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Breaking Change &lt;/p&gt; &lt;div&gt; &lt;p&gt;All handler signatures must be updated. See migration examples below.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;why-this-change&quot;&gt;Why This Change?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The previous &lt;code dir=&quot;auto&quot;&gt;run&lt;/code&gt; wrapper blocked functional composition:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// OLD: The run wrapper created type mismatches&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Root steps received: { run: flowInput }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Dependent steps received: { run: flowInput, dep1: output1 }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// This meant subflows couldn&apos;t compose cleanly:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;ChildFlow&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Flow&lt;/span&gt;&lt;span&gt;&amp;#x3C;{ &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; }&gt;&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step&lt;/span&gt;&lt;span&gt;({ slug: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; }, &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// Expected: input.data&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// Received: { run: parentInput, prep: { data: &quot;...&quot; } }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// TYPE MISMATCH!&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;By removing the wrapper, outputs from one flow can become inputs to another without transformation.&lt;/p&gt;
&lt;aside aria-label=&quot;Future Feature&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Future Feature &lt;/p&gt; &lt;div&gt; &lt;p&gt;Flow composition (subflows) will be implemented in upcoming releases. This breaking change lays the groundwork by ensuring handler signatures are compatible with composable flows.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;upgrading-your-flows&quot;&gt;Upgrading Your Flows&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Apply these patterns to update your handlers. The red/green highlights show exactly what changes.&lt;/p&gt;
&lt;aside aria-label=&quot;Why is ctx.flowInput async?&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Why is ctx.flowInput async? &lt;/p&gt; &lt;div&gt; &lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;ctx.flowInput&lt;/code&gt; is lazy-loaded to prevent data duplication. For map steps processing thousands of items, including the full flow input in each task would multiply data transfer. Instead, it’s fetched on-demand and cached per run.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h3 id=&quot;migration-patterns&quot;&gt;Migration Patterns&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;root-steps-same-for-step-and-array&quot;&gt;Root Steps (same for &lt;code dir=&quot;auto&quot;&gt;.step&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;.array&lt;/code&gt;)&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// BEFORE&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step&lt;/span&gt;&lt;span&gt;({ slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; }, &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;del&gt;&lt;span&gt;input&lt;/span&gt;&lt;/del&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; { userId: &lt;/span&gt;&lt;del&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;/del&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;userId&lt;/span&gt;&lt;span&gt; };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// AFTER&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step&lt;/span&gt;&lt;span&gt;({ slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; }, &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;ins&gt;&lt;span&gt;flowInput&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; { userId: &lt;/span&gt;&lt;ins&gt;&lt;span&gt;flowInput&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;userId&lt;/span&gt;&lt;span&gt; };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;dependent-steps---needing-flowinput&quot;&gt;Dependent Steps - Needing flowInput&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// BEFORE&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step&lt;/span&gt;&lt;span&gt;({ slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;, dependsOn: [&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;] }, &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;del&gt;&lt;span&gt;input&lt;/span&gt;&lt;/del&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;del&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;/del&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;del&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;/del&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;combine&lt;/span&gt;&lt;span&gt;(data, config);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// AFTER (must be &lt;/span&gt;&lt;ins&gt;&lt;span&gt;async&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step&lt;/span&gt;&lt;span&gt;({ slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;, dependsOn: [&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;] }, &lt;/span&gt;&lt;ins&gt;&lt;span&gt;async&lt;/span&gt;&lt;/ins&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;ins&gt;&lt;span&gt;&lt;span&gt;deps&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;flowInput&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;ins&gt;&lt;span&gt;await &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;flowInput&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;flowInput&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;ins&gt;&lt;span&gt;deps&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;combine&lt;/span&gt;&lt;span&gt;(data, config);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;dependent-steps---not-needing-flowinput-common-case&quot;&gt;Dependent Steps - Not Needing flowInput (Common Case)&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// BEFORE&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step&lt;/span&gt;&lt;span&gt;({ slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;save&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;, dependsOn: [&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;] }, &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;del&gt;&lt;span&gt;input&lt;/span&gt;&lt;/del&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;saveToDb&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;del&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;/del&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// AFTER&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;step&lt;/span&gt;&lt;span&gt;({ slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;save&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;, dependsOn: [&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;] }, &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;ins&gt;&lt;span&gt;deps&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;saveToDb&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;ins&gt;&lt;span&gt;deps&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;map-steps-no-change-needed-if-only-using-item&quot;&gt;Map Steps (no change needed if only using &lt;code dir=&quot;auto&quot;&gt;item&lt;/code&gt;)&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;Most map steps just use &lt;code dir=&quot;auto&quot;&gt;item&lt;/code&gt; and need no changes. Only update if you need &lt;code dir=&quot;auto&quot;&gt;flowInput&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// BEFORE (accessing flowInput)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;({ slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;transform&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;, array: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;items&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; }, &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;item&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;(item);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// AFTER (must be &lt;/span&gt;&lt;ins&gt;&lt;span&gt;async&lt;/span&gt;&lt;/ins&gt;&lt;span&gt; to access flowInput)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;({ slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;transform&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;, array: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;items&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; }, &lt;/span&gt;&lt;ins&gt;&lt;span&gt;async&lt;/span&gt;&lt;/ins&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;ins&gt;&lt;span&gt;&lt;span&gt;item&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;flowInput&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;ins&gt;&lt;span&gt;await &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;flowInput&lt;/span&gt;&lt;/ins&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;(item, flowInput&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;production-upgrade-guide&quot;&gt;Production Upgrade Guide&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The upgrade requires careful coordination to avoid running old code against the new SQL schema.&lt;/p&gt;
&lt;aside aria-label=&quot;Critical: No Workers Running During Migration&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Critical: No Workers Running During Migration &lt;/p&gt; &lt;div&gt; &lt;p&gt;It is &lt;strong&gt;very important&lt;/strong&gt; to ensure:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;All worker functions are &lt;strong&gt;disabled&lt;/strong&gt; (step 2)&lt;/li&gt;
&lt;li&gt;All existing workers have &lt;strong&gt;stopped&lt;/strong&gt; (steps 3-4)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Running workers with old handler signatures against the new SQL schema will cause failures. Deprecated workers will gracefully finish their current task and exit - wait for this to complete before proceeding with the migration.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;ol role=&quot;list&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Update handlers locally and test&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Update all your flow handlers to the new signatures. Test locally:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;supabase&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;functions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;serve&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my-worker&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Disable worker functions&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Prevent cron from starting new workers with old code:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;UPDATE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;worker_functions&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SET&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enabled&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; function_name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;my-worker&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deprecate existing workers&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;UPDATE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;workers&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SET&lt;/span&gt;&lt;span&gt; deprecated_at &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NOW&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; function_name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;my-worker&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;AND&lt;/span&gt;&lt;span&gt; deprecated_at &lt;/span&gt;&lt;span&gt;IS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Deprecated workers finish their current task but won’t call &lt;code dir=&quot;auto&quot;&gt;start_tasks&lt;/code&gt; again - so they won’t be affected by the SQL changes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wait for workers to stop&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Monitor workers until all have exited:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;COUNT&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;workers&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; function_name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;my-worker&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;AND&lt;/span&gt;&lt;span&gt; stopped_at &lt;/span&gt;&lt;span&gt;IS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Wait until this returns &lt;code dir=&quot;auto&quot;&gt;0&lt;/code&gt; before proceeding.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Apply database migration&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;supabase&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;db&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deploy new workers&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;supabase&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;functions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deploy&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my-worker&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enable worker functions&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;UPDATE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;worker_functions&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SET&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enabled&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; function_name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;my-worker&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The pgflow cron automatically starts new workers within seconds.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;other-fixes&quot;&gt;Other Fixes&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Fixed &lt;code dir=&quot;auto&quot;&gt;CONNECT_TIMEOUT&lt;/code&gt; errors on Lovable.dev by switching to &lt;code dir=&quot;auto&quot;&gt;jsr:@oscar6echo/postgres&lt;/code&gt; fork&lt;/li&gt;
&lt;li&gt;Fixed &lt;code dir=&quot;auto&quot;&gt;setTimeout&lt;/code&gt; context binding issue in &lt;code dir=&quot;auto&quot;&gt;@pgflow/client&lt;/code&gt; for browser compatibility&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Questions or issues? Join the &lt;a href=&quot;https://discord.gg/pgflow&quot;&gt;Discord community&lt;/a&gt; or &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues&quot;&gt;open a GitHub issue&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>release</category><category>breaking-change</category><category>migration</category></item><item><title>pgflow 0.11.0: Compilation Configuration Overhaul</title><link>https://www.pgflow.dev/news/pgflow-0-11-0-compilation-config/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-11-0-compilation-config/</guid><pubDate>Fri, 12 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;pgflow 0.11.0 introduces a redesigned compilation configuration system. The new &lt;code dir=&quot;auto&quot;&gt;compilation&lt;/code&gt; option provides clearer semantics and adds support for rapid iteration platforms like Lovable through the &lt;code dir=&quot;auto&quot;&gt;allowDataLoss&lt;/code&gt; flag.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;highlights&quot;&gt;Highlights&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New &lt;code dir=&quot;auto&quot;&gt;compilation&lt;/code&gt; config&lt;/strong&gt; - Grouped compilation options with clearer semantics&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;allowDataLoss&lt;/code&gt; option&lt;/strong&gt; - Enable destructive recompilation in production for rapid iteration&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Breaking change&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;ensureCompiledOnStartup&lt;/code&gt; removed in favor of &lt;code dir=&quot;auto&quot;&gt;compilation&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;whats-new-the-compilation-config&quot;&gt;What’s New: The &lt;code dir=&quot;auto&quot;&gt;compilation&lt;/code&gt; Config&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The compilation behavior is now controlled by a single &lt;code dir=&quot;auto&quot;&gt;compilation&lt;/code&gt; option:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Default: auto-detect environment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;EdgeWorker&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt;(MyFlow);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Skip compilation (flows pre-compiled via CLI)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;EdgeWorker&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt;(MyFlow, { compilation: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Allow destructive recompile in production&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;EdgeWorker&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt;(MyFlow, { compilation: { allowDataLoss: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; } });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;when-to-use-each-option&quot;&gt;When to Use Each Option&lt;/h3&gt;&lt;/div&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Option&lt;/th&gt;&lt;th&gt;Use Case&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;(not set)&lt;/td&gt;&lt;td&gt;Standard development and production - auto-detects environment&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;compilation: false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;CI/CD pipelines with pre-compiled flows&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;compilation: { allowDataLoss: true }&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Rapid iteration platforms (Lovable)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h2 id=&quot;the-allowdataloss-option&quot;&gt;The &lt;code dir=&quot;auto&quot;&gt;allowDataLoss&lt;/code&gt; Option&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;code dir=&quot;auto&quot;&gt;allowDataLoss&lt;/code&gt; flag enables local-development behavior in production environments. When a flow shape mismatch is detected:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deletes the existing flow&lt;/strong&gt; and all its run data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compiles the new flow&lt;/strong&gt; from the TypeScript definition&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Worker continues&lt;/strong&gt; with the new schema&lt;/li&gt;
&lt;/ol&gt;
&lt;aside aria-label=&quot;Data Loss Warning&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Data Loss Warning &lt;/p&gt; &lt;div&gt; &lt;p&gt;Setting &lt;code dir=&quot;auto&quot;&gt;allowDataLoss: true&lt;/code&gt; will &lt;strong&gt;permanently delete all flow data&lt;/strong&gt; (runs, tasks, execution history) when the flow shape changes. This is intentional for rapid iteration but means you lose all previous runs.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h3 id=&quot;target-use-case-lovable-and-similar-platforms&quot;&gt;Target Use Case: Lovable and Similar Platforms&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;allowDataLoss&lt;/code&gt; option was designed for platforms like &lt;a href=&quot;https://lovable.dev&quot;&gt;Lovable&lt;/a&gt; where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Flow definitions change frequently during development&lt;/li&gt;
&lt;li&gt;Execution history doesn’t need to persist between iterations&lt;/li&gt;
&lt;li&gt;Speed of iteration matters more than data durability&lt;/li&gt;
&lt;li&gt;Users expect “just works” behavior without manual intervention&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;ensurecompiledonstartup-removed&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;ensureCompiledOnStartup&lt;/code&gt; Removed&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;ensureCompiledOnStartup&lt;/code&gt; option has been replaced by the new &lt;code dir=&quot;auto&quot;&gt;compilation&lt;/code&gt; config.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Before (0.10.x):&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Skip compilation&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;EdgeWorker&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt;(MyFlow, { ensureCompiledOnStartup: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Enable compilation (default)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;EdgeWorker&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt;(MyFlow, { ensureCompiledOnStartup: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;After (0.11.0):&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Skip compilation&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;EdgeWorker&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt;(MyFlow, { compilation: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Enable compilation (default) - just don&apos;t set the option&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;EdgeWorker&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt;(MyFlow);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;migration-guide&quot;&gt;Migration Guide&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;If you were using &lt;code dir=&quot;auto&quot;&gt;ensureCompiledOnStartup&lt;/code&gt;:&lt;/p&gt;

















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Old Config&lt;/th&gt;&lt;th&gt;New Config&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;ensureCompiledOnStartup: true&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Remove (or use &lt;code dir=&quot;auto&quot;&gt;compilation: {}&lt;/code&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;ensureCompiledOnStartup: false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;compilation: false&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h2 id=&quot;upgrade-now&quot;&gt;Upgrade Now&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Follow the standard &lt;a href=&quot;https://www.pgflow.dev/deploy/update-pgflow/&quot;&gt;Update pgflow&lt;/a&gt; guide to update packages and apply migrations.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;quick-migration&quot;&gt;Quick Migration&lt;/h3&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Update your packages:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow@latest&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Find and replace in your worker files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;ensureCompiledOnStartup: false&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;compilation: false&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;ensureCompiledOnStartup: true&lt;/code&gt; → remove the option entirely&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Apply database migrations:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;supabase&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;db&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>release</category><category>compilation</category><category>configuration</category><category>breaking-change</category></item><item><title>pgflow 0.10.0: Auto-Compilation and Worker Management</title><link>https://www.pgflow.dev/news/pgflow-0-10-0-auto-compilation-and-worker-management/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-10-0-auto-compilation-and-worker-management/</guid><pubDate>Wed, 10 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;pgflow 0.10.0 is a developer experience milestone. This release eliminates two of the biggest friction points in pgflow development: manual flow compilation and worker lifecycle management.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;highlights&quot;&gt;Highlights&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Auto-compilation at startup&lt;/strong&gt; - Workers verify and compile flows automatically&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Intelligent worker management&lt;/strong&gt; - Database-driven cron keeps workers running reliably&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Beautiful local logging&lt;/strong&gt; - Colored output with retry information and exponential backoff display&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;auto-compilation-never-compile-manually-again&quot;&gt;Auto-Compilation: Never Compile Manually Again&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Previously, every flow change required running &lt;code dir=&quot;auto&quot;&gt;pgflow compile&lt;/code&gt;, dropping old flow data with ‘pgflow.delete_flow_and_data()’ and migrating database, all before you can test your flow. This release introduces automatic flow compilation and previous version deletion that happens when workers start.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;how-it-works&quot;&gt;How It Works&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;When a worker starts, it calls the new &lt;code dir=&quot;auto&quot;&gt;ensure_flow_compiled()&lt;/code&gt; function which:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Checks if the flow exists&lt;/strong&gt; - If not, compiles it immediately&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compares flow shapes&lt;/strong&gt; - Verifies the TypeScript definition matches the database&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto-recompiles in development&lt;/strong&gt; - Detects local Supabase and just deletes previous version and compiles new one&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fails safely in production&lt;/strong&gt; - Returns an error instead of deleting/recompiling&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h3 id=&quot;why-this-matters&quot;&gt;Why This Matters&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;This achieves full &lt;strong&gt;watch-mode&lt;/strong&gt; in local &lt;strong&gt;development&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Change your flow definition in TypeScript&lt;/li&gt;
&lt;li&gt;Supabase detects the change and starts new function&lt;/li&gt;
&lt;li&gt;Cron polls the function, starting new worker automatically&lt;/li&gt;
&lt;li&gt;Flow is compiled and ready - no manual step required&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And a convenient “deploy updated flow, no need for migrations” workflow on &lt;strong&gt;production&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Production worker only compiles new flows&lt;/li&gt;
&lt;li&gt;Mismatches are caught immediately with clear error messages, worker refuses to start&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;configuration&quot;&gt;Configuration&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Auto-compilation is enabled by default. To opt out:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;EdgeWorker&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt;(MyFlow, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ensureCompiledOnStartup: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;worker-management-set-it-and-forget-it&quot;&gt;Worker Management: Set It and Forget It&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Managing worker lifecycles on hosted Supabase has been a pain point. Edge Functions have CPU time limits, worker contantly respanw themselves for continuos operation and to make it reliable one needed to setup a manual cron schedule.&lt;/p&gt;
&lt;p&gt;pgflow 0.10.0 introduces built-in worker management that handles all of this automatically.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;the-worker-management-system&quot;&gt;The Worker Management System&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Each worker function (edge function having EdgeWorker.start()) is tracked in new &lt;code dir=&quot;auto&quot;&gt;pgflow.worker_functions&lt;/code&gt; table.&lt;/p&gt;
&lt;p&gt;When you install 0.10.0 migrations, it will setup a new &lt;code dir=&quot;auto&quot;&gt;pgflow_ensure_workers&lt;/code&gt; cron job runs every second and:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Tracks registered workers&lt;/strong&gt; from the &lt;code dir=&quot;auto&quot;&gt;worker_functions&lt;/code&gt; table&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Detects dead workers&lt;/strong&gt; - Uses heartbeats and &lt;code dir=&quot;auto&quot;&gt;stopped_at&lt;/code&gt; timestamps&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Invokes workers when needed&lt;/strong&gt; - Pings edge functions via HTTP to spawn new workers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Debounces intelligently&lt;/strong&gt; - Prevents spawning too many workers simultaneously&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Only invokes HTTP requests&lt;/strong&gt; when needed, saving on invocations and egress.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h3 id=&quot;why-this-matters-1&quot;&gt;Why This Matters&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Before 0.10.0:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set up manual &lt;code dir=&quot;auto&quot;&gt;pg_cron&lt;/code&gt; jobs with watchdog logic&lt;/li&gt;
&lt;li&gt;Workers died and stayed dead until manually restarted&lt;/li&gt;
&lt;li&gt;Risk of spawning too many workers under load&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;After 0.10.0:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Workers register themselves automatically&lt;/li&gt;
&lt;li&gt;Dead workers are detected and replaced within seconds&lt;/li&gt;
&lt;li&gt;Debouncing prevents worker storms&lt;/li&gt;
&lt;li&gt;Graceful shutdown signals prevent false-positive restarts&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;production-credentials&quot;&gt;Production Credentials&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The worker management system uses Vault secrets to invoke edge functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;supabase_service_role_key&lt;/code&gt; - For authentication&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;supabase_project_id&lt;/code&gt; - To build the function URL&lt;/li&gt;
&lt;/ul&gt;
&lt;aside aria-label=&quot;Local Development&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Local Development &lt;/p&gt; &lt;div&gt; &lt;p&gt;In local development, the system automatically uses &lt;code dir=&quot;auto&quot;&gt;http://kong:8000/functions/v1&lt;/code&gt; without authentication, so you don’t need to configure anything for local testing.&lt;/p&gt;&lt;p&gt;It will also ping functions every 1s without any debounce in order to respawn new workers after a code change as soon as possible.
You can override this by calling &lt;code dir=&quot;auto&quot;&gt;pgflow.setup_ensure_workers_cron(&apos;10 seconds&apos;)&lt;/code&gt; with your value manually.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;structured-logging-see-what-matters&quot;&gt;Structured Logging: See What Matters&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new logging system adapts to your environment automatically.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;local-development-fancy-format&quot;&gt;Local Development (Fancy Format)&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;starlight-image-zoom-zoomable&gt;&lt;img src=&quot;https://www.pgflow.dev/_astro/logger-output.I8GcWVv3_16Vdpp.webp&quot; alt=&quot;Logger output showing colored status icons, worker prefixes, and retry information&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1102&quot; height=&quot;468&quot;&gt;&lt;button aria-label=&quot;Zoom image: Logger output showing colored status icons, worker prefixes, and retry information&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/starlight-image-zoom-zoomable&gt;&lt;/p&gt;
&lt;p&gt;Features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Colored icons (green checkmarks, red X, yellow retry arrows)&lt;/li&gt;
&lt;li&gt;Worker-prefixed lines for multi-worker clarity&lt;/li&gt;
&lt;li&gt;Flow/step paths for context&lt;/li&gt;
&lt;li&gt;Retry countdown with exponential backoff calculation&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;production-simple-format&quot;&gt;Production (Simple Format)&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[INFO] worker=analyze-website queue=pgflow_tasks flow=analyze_website status=verified worker_id=abc123&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[VERBOSE] worker=analyze-website flow=analyze_website step=scrape status=completed duration_ms=127&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[VERBOSE] worker=analyze-website flow=analyze_website step=analyze status=failed error=&quot;Rate limit&quot; retry=1/3 retry_delay_s=5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Structured &lt;code dir=&quot;auto&quot;&gt;key=value&lt;/code&gt; format for log aggregators&lt;/li&gt;
&lt;li&gt;Appropriate log levels (INFO, VERBOSE, DEBUG)&lt;/li&gt;
&lt;li&gt;All context included for filtering and alerting&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;configuration-1&quot;&gt;Configuration&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The format is auto-detected based on environment, but you can override:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Force fancy format in production (not recommended)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;EDGE_WORKER_LOG_FORMAT&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;fancy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Set log level explicitly&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;EDGE_WORKER_LOG_LEVEL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;debug&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# error &amp;#x3C; warn &amp;#x3C; info &amp;#x3C; verbose &amp;#x3C; debug&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Disable colors (respects NO_COLOR standard)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;NO_COLOR&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside aria-label=&quot;Tip&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Tip &lt;/p&gt; &lt;div&gt; &lt;p&gt;For filtering Supabase Edge Runtime noise during local development, see &lt;a href=&quot;https://www.pgflow.dev/build/local-development/&quot;&gt;Local Development&lt;/a&gt;.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;None. All new features are additive and existing workflows continue to work unchanged.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;upgrade-now&quot;&gt;Upgrade Now&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Follow the standard &lt;a href=&quot;https://www.pgflow.dev/deploy/update-pgflow/&quot;&gt;Update pgflow&lt;/a&gt; guide to update packages and apply migrations.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;remove-old-watchdog-cron-jobs&quot;&gt;Remove Old Watchdog Cron Jobs&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;pgflow now sets up the &lt;code dir=&quot;auto&quot;&gt;pgflow_ensure_workers&lt;/code&gt; cron automatically during migration. If you previously set up manual cron jobs to keep workers running (from older documentation), remove them:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;-- Check for old watchdog jobs&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; jobid, jobname, schedule, command&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cron&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;job&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; jobname &lt;/span&gt;&lt;span&gt;LIKE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;%watchdog%&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;OR&lt;/span&gt;&lt;span&gt; command &lt;/span&gt;&lt;span&gt;LIKE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;%invoke%function%&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;-- Remove old jobs (replace ID with actual jobid)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cron&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;unschedule&lt;/span&gt;&lt;span&gt;(jobid) &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cron&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;job&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; jobname &lt;/span&gt;&lt;span&gt;LIKE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;%watchdog%&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Questions or issues? Open a &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues&quot;&gt;GitHub issue&lt;/a&gt; or join the discussion on &lt;a href=&quot;https://pgflow.dev/discord/&quot;&gt;Discord&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>release</category><category>auto-compilation</category><category>worker-management</category><category>developer-experience</category></item><item><title>pgflow 0.9.1: Unified Connection Configuration</title><link>https://www.pgflow.dev/news/pgflow-0-9-1-unified-connection-configuration/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-9-1-unified-connection-configuration/</guid><pubDate>Tue, 02 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This release unifies how the edge worker handles database connections - zero-config local development, a clear priority chain, and proper SSL support.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;whats-new&quot;&gt;What’s New&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;connectionString now works&lt;/strong&gt; (&lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/469&quot;&gt;#469&lt;/a&gt;, &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/424&quot;&gt;#424&lt;/a&gt;) - The &lt;code dir=&quot;auto&quot;&gt;connectionString&lt;/code&gt; config option was being ignored. Now it works, enabling patterns like falling back to &lt;code dir=&quot;auto&quot;&gt;SUPABASE_DB_URL&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pass raw postgres.js connection&lt;/strong&gt; - Use &lt;code dir=&quot;auto&quot;&gt;config.sql&lt;/code&gt; to pass your own &lt;a href=&quot;https://github.com/porsager/postgres&quot;&gt;postgres.js&lt;/a&gt; instance with custom options (SSL, connection pooling, etc.).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero-config local dev&lt;/strong&gt; - When local environment is detected (via known local dev keys), the worker automatically connects to the local transaction pooler. No environment variables needed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cleaner install&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;pgflow install&lt;/code&gt; no longer writes &lt;code dir=&quot;auto&quot;&gt;EDGE_WORKER_DB_URL&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;.env&lt;/code&gt; since local dev works without it.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;connection-priority&quot;&gt;Connection Priority&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The edge worker now resolves database connections in this order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;config.sql&lt;/code&gt; - Full control with custom postgres instance&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;config.connectionString&lt;/code&gt; - Explicit URL in code&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;EDGE_WORKER_DB_URL&lt;/code&gt; - Environment variable&lt;/li&gt;
&lt;li&gt;Local fallback - Auto-detected local Supabase pooler&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If nothing is configured and local Supabase is not detected, the worker throws a clear error explaining the options.&lt;/p&gt;
&lt;aside aria-label=&quot;Backward Compatible&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Backward Compatible &lt;/p&gt; &lt;div&gt; &lt;p&gt;Existing configurations continue to work. If you have &lt;code dir=&quot;auto&quot;&gt;EDGE_WORKER_DB_URL&lt;/code&gt; set or use &lt;code dir=&quot;auto&quot;&gt;config.sql&lt;/code&gt;, no changes are needed.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;new-documentation&quot;&gt;New Documentation&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The Supabase deployment guide has been revamped from a single page into a structured overview with dedicated pages for each topic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/deploy/supabase/&quot;&gt;Supabase Deployment Overview&lt;/a&gt; - Step-by-step guide structure&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/deploy/database-connection/&quot;&gt;Database Connection&lt;/a&gt; - Overview of connection options&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/deploy/supabase/preview-branches/&quot;&gt;Preview Branches&lt;/a&gt; - Handling dynamic environments&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/deploy/database-ssl/&quot;&gt;Database SSL&lt;/a&gt; - Configuring SSL for external databases&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/deploy/troubleshooting-connections/&quot;&gt;Troubleshooting Connections&lt;/a&gt; - Common issues and solutions&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;issues-addressed&quot;&gt;Issues Addressed&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/469&quot;&gt;#469&lt;/a&gt; - &lt;code dir=&quot;auto&quot;&gt;connectionString&lt;/code&gt; config was being ignored&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/424&quot;&gt;#424&lt;/a&gt; - Simplified local development setup&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pgflow-dev/pgflow/discussions/280&quot;&gt;Discussion #280&lt;/a&gt; - Preview branch connection patterns&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;thanks&quot;&gt;Thanks&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release was shaped by community feedback. Thanks to &lt;a href=&quot;https://github.com/Nciso&quot;&gt;Nciso&lt;/a&gt;, &lt;a href=&quot;https://github.com/mikz&quot;&gt;mikz&lt;/a&gt;, &lt;a href=&quot;https://github.com/ddlaws0n&quot;&gt;ddlaws0n&lt;/a&gt;, and &lt;strong&gt;PixelEcho&lt;/strong&gt; (Discord) for reporting issues, suggesting improvements, and helping improve the documentation.&lt;/p&gt;</content:encoded><category>release</category><category>edge-worker</category><category>configuration</category></item><item><title>pgflow 0.9.0: Control Plane and HTTP-Based Compilation</title><link>https://www.pgflow.dev/news/pgflow-0-9-0-control-plane-and-http-based-compilation/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-9-0-control-plane-and-http-based-compilation/</guid><pubDate>Fri, 28 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;pgflow 0.9.0 introduces the ControlPlane edge function, enabling HTTP-based flow compilation without requiring a local Deno installation.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-changed&quot;&gt;What Changed&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The CLI no longer spawns Deno processes locally. Instead, compilation requests go through the ControlPlane edge function:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;pgflow compile my_flow  --&gt;  ControlPlane  --&gt;  SQL migration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This simplifies the development setup and lays groundwork for future auto-compilation features where workers will verify and compile flows at startup without any CLI involvement.&lt;/p&gt;
&lt;aside aria-label=&quot;Future Direction&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Future Direction &lt;/p&gt; &lt;div&gt; &lt;p&gt;This release prepares for upcoming changes where edge workers will automatically verify flow shapes and trigger compilation when needed - making &lt;code dir=&quot;auto&quot;&gt;pgflow compile&lt;/code&gt; optional for development workflows.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;compile-command&quot;&gt;Compile Command&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;pgflow compile&lt;/code&gt; command now takes a &lt;strong&gt;flow slug&lt;/strong&gt; instead of a file path:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Before (0.8.x):&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compile&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path/to/my_flow.ts&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--deno-json&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;supabase/functions/deno.json&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;After (0.9.0):&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compile&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my_flow&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;--deno-json&lt;/code&gt; flag has been removed.&lt;/p&gt;
&lt;aside aria-label=&quot;Need the Old Behavior?&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Need the Old Behavior? &lt;/p&gt; &lt;div&gt; &lt;p&gt;If you need local Deno compilation, you can use the previous version:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow@0.8.0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compile&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path/to/flow.ts&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;new-install-experience&quot;&gt;New Install Experience&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The installer now scaffolds a complete working setup:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow@0.9.0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This creates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;supabase/flows/&lt;/code&gt; - Directory for flow definitions with namespace imports&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;supabase/flows/greet-user.ts&lt;/code&gt; - Example GreetUser flow&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;supabase/functions/pgflow/&lt;/code&gt; - Control Plane for compilation&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;supabase/functions/greet-user-worker/&lt;/code&gt; - Example worker ready to run&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The installer shows a clear summary and asks for a single confirmation before making changes.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;namespace-imports-for-flows&quot;&gt;Namespace Imports for Flows&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ControlPlane now supports namespace imports, the recommended pattern:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { ControlPlane } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;@pgflow/edge-worker&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; flows &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;../../flows/index.ts&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ControlPlane&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;serve&lt;/span&gt;&lt;span&gt;(flows);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Add flows by exporting from &lt;code dir=&quot;auto&quot;&gt;flows/index.ts&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; { GreetUser } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;./greet-user.ts&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; { MyOtherFlow } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;./my-other-flow.ts&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;upgrading-from-v08x&quot;&gt;Upgrading from v0.8.x&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Existing compiled flows continue to work&lt;/strong&gt; - no recompilation needed.&lt;/p&gt;
&lt;p&gt;To compile &lt;strong&gt;new flows&lt;/strong&gt; with v0.9.0:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Run &lt;code dir=&quot;auto&quot;&gt;npx pgflow@0.9.0 install&lt;/code&gt; to add the ControlPlane and &lt;code dir=&quot;auto&quot;&gt;supabase/flows/&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;Create new flow files in &lt;code dir=&quot;auto&quot;&gt;supabase/flows/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Export them from &lt;code dir=&quot;auto&quot;&gt;supabase/flows/index.ts&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;aside aria-label=&quot;Existing Flows&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Existing Flows &lt;/p&gt; &lt;div&gt; &lt;p&gt;You don’t need to move existing flow files. The new structure is only for
flows you want to compile going forward. Move old flows only if you want
consistency in your project structure.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h3 id=&quot;removed-deno-json-flag&quot;&gt;Removed: —deno-json flag&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;--deno-json&lt;/code&gt; flag has been removed. Compilation now uses the ControlPlane
edge function instead of local Deno. If you used this flag in CI/CD scripts,
update them to use the new compilation approach.&lt;/p&gt;</content:encoded><category>release</category><category>control-plane</category><category>compilation</category></item><item><title>pgflow 0.8.0: Modernizing Dependencies - pgmq 1.5.0 and PostgreSQL 17</title><link>https://www.pgflow.dev/news/pgflow-0-8-0-modernizing-dependencies-pgmq-1-5-0-and-postgresql-17/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-8-0-modernizing-dependencies-pgmq-1-5-0-and-postgresql-17/</guid><pubDate>Tue, 18 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;pgflow 0.8.0 requires pgmq 1.5.0 or higher and PostgreSQL 17. This release removes the pgmq compatibility layer and prepares the foundation for upcoming flow auto-compilation features.&lt;/p&gt;
&lt;aside aria-label=&quot;Breaking Change&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Breaking Change&lt;/p&gt;&lt;div&gt;&lt;p&gt;This version &lt;strong&gt;will NOT work with pgmq 1.4.x or earlier&lt;/strong&gt;. The migration includes a compatibility check that will abort with a clear error message if pgmq 1.5.0 is not detected.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;whats-changing&quot;&gt;What’s Changing&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;pgflow 0.8.0 introduces breaking dependency changes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;pgmq version&lt;/strong&gt;: Now requires 1.5.0 or higher (previously supported 1.4.x)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PostgreSQL version&lt;/strong&gt;: Upgrades to PostgreSQL 17 (from 15)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Supabase CLI&lt;/strong&gt;: Requires version 2.50.3 or higher (includes pgmq 1.5.0+)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deno version&lt;/strong&gt;: Now requires 2.1.x or higher (previously 1.45.x)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The migration will fail safely if these requirements are not met - no partial upgrades or corrupted state.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release skips backward compatibility entirely - pgflow 0.8.0 requires pgmq 1.5.0 from the start. Maintaining compatibility layers for older versions would accumulate technical debt that becomes harder to remove as the project matures.&lt;/p&gt;
&lt;p&gt;Additionally, upcoming features like flow auto-compilation depend on infrastructure available only in newer Supabase versions (automatic edge function respawning in local development). Moving to pgmq 1.5.0 and PostgreSQL 17 unblocks these improvements.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;before-you-upgrade&quot;&gt;Before You Upgrade&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;check-your-pgmq-version&quot;&gt;Check Your pgmq Version&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Run this query to verify your current pgmq version:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; extversion &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; pg_extension &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; extname &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;pgmq&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;You need version 1.5.0 or higher to upgrade to pgflow 0.8.0.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;check-your-deno-version&quot;&gt;Check Your Deno Version&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Verify your Deno installation meets the minimum requirement:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;deno&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--version&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;You need Deno 2.1.x or higher (previously 1.45.x). If you need to upgrade, see the &lt;a href=&quot;https://docs.deno.com/runtime/getting_started/installation/&quot;&gt;Deno installation guide&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;compatibility-check-built-in&quot;&gt;Compatibility Check Built-In&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The migration includes a pre-check that inspects the pgmq schema before making any changes. If pgmq 1.5.0 is not detected, the migration aborts with this error:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ERROR: INCOMPATIBLE PGMQ VERSION DETECTED&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;This migration requires pgmq 1.5.0 or higher.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;The pgmq.message_record type is missing the &quot;headers&quot; column,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;which indicates you are running pgmq &amp;#x3C; 1.5.0.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Action required:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- Supabase: Ensure you are running a recent version that includes pgmq 1.5.0+&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- Self-hosted: Upgrade pgmq to version 1.5.0 or higher before running this migration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Migration aborted to prevent runtime failures.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This safety check prevents partial migrations and data corruption.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;migration-guide&quot;&gt;Migration Guide&lt;/h2&gt;&lt;/div&gt;
&lt;aside aria-label=&quot;Older Supabase Projects Need a Platform Upgrade&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Older Supabase Projects Need a Platform Upgrade&lt;/p&gt;&lt;div&gt;&lt;p&gt;If your existing Supabase project has pgmq 1.4.x, you must &lt;strong&gt;upgrade your Supabase project first&lt;/strong&gt; - projects don’t auto-upgrade. Follow the &lt;a href=&quot;https://supabase.com/docs/guides/platform/upgrading&quot;&gt;Supabase Platform Upgrade Guide&lt;/a&gt; to get pgmq 1.5.0+.&lt;/p&gt;&lt;p&gt;pgflow tracks current Supabase platform releases and does not support older versions. If you cannot upgrade immediately, stay on pgflow 0.7.x until you’re ready.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;h3 id=&quot;supabase-cloud-users&quot;&gt;Supabase Cloud Users&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Supabase CLI version 2.50.3 or higher includes pgmq 1.5.0 by default.&lt;/p&gt;
&lt;ol role=&quot;list&quot;&gt;
&lt;li&gt;
&lt;p&gt;Update your Supabase CLI if needed:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;supabase&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Check current version&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-g&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;supabase&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Update if below 2.50.3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Verify your pgmq version using the SQL query above&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run your migrations:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;supabase&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;db&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h3 id=&quot;self-hosted-users&quot;&gt;Self-Hosted Users&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;You must upgrade pgmq to 1.5.0+ before upgrading pgflow.&lt;/p&gt;
&lt;ol role=&quot;list&quot;&gt;
&lt;li&gt;
&lt;p&gt;Check your current pgmq version&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Upgrade pgmq to 1.5.0 or higher following the &lt;a href=&quot;https://github.com/tembo-io/pgmq&quot;&gt;pgmq upgrade guide&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Upgrade PostgreSQL to version 17 if not already running it&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run your pgflow migrations:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;supabase&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;db&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;For questions or issues with the upgrade, visit the &lt;a href=&quot;https://www.pgflow.dev/discord/&quot;&gt;pgflow Discord&lt;/a&gt; or &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues&quot;&gt;open a GitHub issue&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>release</category><category>breaking-change</category><category>migration</category></item><item><title>pgflow 0.7.3: Improved Supabase Realtime Connection Reliability</title><link>https://www.pgflow.dev/news/pgflow-0-7-3-improved-supabase-realtime-connection-reliability/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-7-3-improved-supabase-realtime-connection-reliability/</guid><pubDate>Mon, 17 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;pgflow 0.7.3 introduces a configurable &lt;code dir=&quot;auto&quot;&gt;realtimeStabilizationDelayMs&lt;/code&gt; option that addresses a known Supabase Realtime limitation where backend routing isn’t fully established when the SUBSCRIBED event is emitted.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;whats-new&quot;&gt;What’s New&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The TypeScript client now includes a &lt;code dir=&quot;auto&quot;&gt;realtimeStabilizationDelayMs&lt;/code&gt; configuration option (default: 300ms) that adds a delay after subscribing to Realtime channels. This works around a &lt;a href=&quot;https://github.com/supabase/supabase-js/issues/1599&quot;&gt;known Supabase Realtime issue&lt;/a&gt; where messages sent immediately after subscription confirmation may be missed because backend routing takes additional time to fully establish.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When starting flows or retrieving runs&lt;/strong&gt;, the client waits for this stabilization period after receiving the SUBSCRIBED event, ensuring that all subsequent realtime events are properly received.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;configuration&quot;&gt;Configuration&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The default 300ms delay works reliably in most environments. If you experience missed events or connection issues, increase the delay to 400-500ms:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { PgflowClient } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;@pgflow/client&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Increase stabilization delay for unreliable connections&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PgflowClient&lt;/span&gt;&lt;span&gt;(supabase&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;realtimeStabilizationDelayMs: &lt;/span&gt;&lt;span&gt;400&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;You can also disable the delay by setting it to 0, though this may cause missed events in some environments:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Disable delay (may cause missed events)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PgflowClient&lt;/span&gt;&lt;span&gt;(supabase&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;realtimeStabilizationDelayMs: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;See the &lt;a href=&quot;https://www.pgflow.dev/build/starting-flows/typescript-client/&quot;&gt;TypeScript Client documentation&lt;/a&gt; and &lt;a href=&quot;https://www.pgflow.dev/reference/pgflow-client/&quot;&gt;PgflowClient API reference&lt;/a&gt; for complete details.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;upgrading&quot;&gt;Upgrading&lt;/h2&gt;&lt;/div&gt;
&lt;aside aria-label=&quot;No Migration Required&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; No Migration Required &lt;/p&gt; &lt;div&gt; &lt;p&gt;This release only updates the TypeScript client package. No database migrations are needed.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;p&gt;Follow the &lt;a href=&quot;https://www.pgflow.dev/deploy/update-pgflow/&quot;&gt;update guide&lt;/a&gt; to upgrade your &lt;code dir=&quot;auto&quot;&gt;@pgflow/client&lt;/code&gt; dependency to 0.7.3.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Questions or issues?&lt;/strong&gt; Join our &lt;a href=&quot;https://www.pgflow.dev/discord/&quot;&gt;Discord community&lt;/a&gt; or &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues&quot;&gt;open an issue on GitHub&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>bugfix</category><category>realtime</category><category>client</category></item><item><title>pgflow 0.7.2: Fix Missing Realtime Broadcasts for Step Events</title><link>https://www.pgflow.dev/news/pgflow-0-7-2-fix-missing-realtime-broadcasts-for-step-events/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-7-2-fix-missing-realtime-broadcasts-for-step-events/</guid><pubDate>Tue, 04 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;pgflow 0.7.2 fixes missing realtime broadcasts that prevented clients from receiving &lt;code dir=&quot;auto&quot;&gt;step:started&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;step:completed&lt;/code&gt; events. PostgreSQL’s query optimizer was eliminating CTEs containing &lt;code dir=&quot;auto&quot;&gt;realtime.send()&lt;/code&gt; calls because they weren’t referenced by subsequent operations.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;whats-fixed&quot;&gt;What’s Fixed&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;step:started&lt;/code&gt; events now broadcast when steps begin executing&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;step:completed&lt;/code&gt; events now broadcast for empty map steps&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;step:completed&lt;/code&gt; events now broadcast for cascade completions&lt;/li&gt;
&lt;li&gt;Client applySnapshot() methods added for proper initial state hydration without event emission&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;additional-changes&quot;&gt;Additional Changes&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Enhanced test coverage for realtime event lifecycles&lt;/li&gt;
&lt;li&gt;Documentation updates for abort signal support and empty map step behavior&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;upgrading&quot;&gt;Upgrading&lt;/h2&gt;&lt;/div&gt;
&lt;aside aria-label=&quot;Migration Required&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Migration Required &lt;/p&gt; &lt;div&gt; &lt;p&gt;This release includes database migrations. See the &lt;a href=&quot;https://www.pgflow.dev/deploy/update-pgflow/&quot;&gt;update guide&lt;/a&gt; for instructions.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Questions or issues?&lt;/strong&gt; Join our &lt;a href=&quot;https://www.pgflow.dev/discord/&quot;&gt;Discord community&lt;/a&gt; or &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues&quot;&gt;open an issue on GitHub&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>bugfix</category><category>realtime</category><category>client</category><category>core</category></item><item><title>pgflow 0.7.1: Fix pgmq 1.5.1 Version Conflict on New Supabase Projects</title><link>https://www.pgflow.dev/news/pgflow-0-7-1-fix-pgmq-version-conflict-with-supabase-1-5-1/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-7-1-fix-pgmq-version-conflict-with-supabase-1-5-1/</guid><pubDate>Thu, 30 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;pgflow 0.7.1 fixes installation failures on fresh Supabase projects caused by pgmq version mismatch.&lt;/p&gt;
&lt;aside aria-label=&quot;Existing Projects Unaffected&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Existing Projects Unaffected &lt;/p&gt; &lt;div&gt; &lt;p&gt;If you already have pgflow installed, you’re completely unaffected. This fix only impacts fresh installations on new Supabase projects. No action needed, no code changes, and no need to update to 0.7.1.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;the-bug&quot;&gt;The Bug&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Installing pgflow on new Supabase projects failed with:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ERROR: extension &quot;pgmq&quot; has no installation script nor update path for version &quot;1.4.4&quot; (SQLSTATE 22023)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;At statement: 2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;CREATE EXTENSION IF NOT EXISTS &quot;pgmq&quot; WITH SCHEMA &quot;pgmq&quot; VERSION &quot;1.4.4&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;why-it-happened&quot;&gt;Why It Happened&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Supabase upgraded to pgmq 1.5.1 in Postgres 17.6.1.016+ (&lt;a href=&quot;https://github.com/supabase/postgres/pull/1668&quot;&gt;supabase/postgres#1668&lt;/a&gt;). pgflow’s initial migration was pinned to version 1.4.4, which no longer exists in new Supabase instances.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-fix&quot;&gt;The Fix&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Removed the version constraint from pgmq extension creation. pgflow now uses whatever pgmq version Supabase provides (1.4.4, 1.5.1, or newer).&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; EXTENSION &lt;/span&gt;&lt;span&gt;IF&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NOT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;EXISTS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;pgmq&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;WITH&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SCHEMA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;pgmq&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VERSION&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;1.4.4&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; EXTENSION &lt;/span&gt;&lt;span&gt;IF&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NOT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;EXISTS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;pgmq&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;WITH&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SCHEMA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;pgmq&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;credits&quot;&gt;Credits&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://github.com/kallebysantos/&quot;&gt;@kallebysantos&lt;/a&gt; for reporting this issue!&lt;/p&gt;</content:encoded><category>bugfix</category><category>supabase</category><category>pgmq</category></item><item><title>pgflow 0.7.0: Public Beta with Map Steps and Documentation Redesign</title><link>https://www.pgflow.dev/news/pgflow-0-7-0-public-beta-map-steps-and-documentation-redesign/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-7-0-public-beta-map-steps-and-documentation-redesign/</guid><pubDate>Sun, 19 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;pgflow 0.7.0 is here - a major milestone that brings parallel array processing,
production-ready stability, and a complete documentation redesign.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;pgflow-enters-public-beta&quot;&gt;pgflow Enters Public Beta&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;pgflow has transitioned from alpha to &lt;strong&gt;public beta&lt;/strong&gt;. Core functionality is stable and reliable,
with early adopters already running pgflow in production environments.&lt;/p&gt;
&lt;p&gt;This milestone reflects months of testing, bug fixes, and real-world usage feedback. The SQL Core,
DSL, and Edge Worker components have proven robust across different workloads and deployment scenarios.&lt;/p&gt;
&lt;p&gt;See the &lt;a href=&quot;https://www.pgflow.dev/project-status/&quot;&gt;project status page&lt;/a&gt; for production recommendations and known limitations.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;map-steps&quot;&gt;Map Steps&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Map steps enable parallel array processing by automatically creating multiple tasks - one for each array element.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Flow } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;@pgflow/dsl/supabase&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;BatchProcessor&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Flow&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;batchProcessor&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;maxAttempts: &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{ slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;processUrls&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;// Each URL gets its own task with independent retry&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;scrapeWebpage&lt;/span&gt;&lt;span&gt;(url);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When processing 100 URLs, if URL #47 fails, only that specific task retries - the other 99 continue
processing. With a regular step, one failure would retry all 100 URLs.&lt;/p&gt;
&lt;p&gt;This independent retry isolation makes flows more efficient and resilient. Each task has its own
retry counter, timeout, and execution context.&lt;/p&gt;
&lt;p&gt;Map steps handle edge cases automatically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Empty arrays complete immediately without creating tasks&lt;/li&gt;
&lt;li&gt;Type violations fail gracefully with stored output for debugging&lt;/li&gt;
&lt;li&gt;Results maintain array order regardless of completion sequence&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Learn more: &lt;a href=&quot;https://www.pgflow.dev/concepts/map-steps/&quot;&gt;Map Steps&lt;/a&gt; and &lt;a href=&quot;https://www.pgflow.dev/build/process-arrays-in-parallel/&quot;&gt;Process Arrays in Parallel&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;array-steps&quot;&gt;Array Steps&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;code dir=&quot;auto&quot;&gt;.array()&lt;/code&gt; method provides compile-time type safety for array-returning handlers:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Enforces array return type at compile time&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;flow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;array&lt;/span&gt;&lt;span&gt;({ slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;items&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; }, &lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;]);  &lt;/span&gt;&lt;span&gt;// Valid&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;flow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;array&lt;/span&gt;&lt;span&gt;({ slug: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;invalid&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; }, &lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;span&gt;);  &lt;/span&gt;&lt;span&gt;// Compile error&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Array steps are a semantic wrapper that makes intent clear and moves type errors from &lt;code dir=&quot;auto&quot;&gt;.map()&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;.array()&lt;/code&gt;. When a map step depends on a regular step that doesn’t return an array, the compiler catches it too - &lt;code dir=&quot;auto&quot;&gt;.array()&lt;/code&gt; just makes the error location more precise and the code intention explicit.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;typescript-client---now-fully-documented&quot;&gt;TypeScript Client - Now Fully Documented&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The &lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;@pgflow/client&lt;/code&gt;&lt;/strong&gt; package, initially released in v0.4.0 but never widely announced, now has complete documentation. This &lt;strong&gt;type-safe client&lt;/strong&gt; powers the &lt;a href=&quot;https://www.pgflow.dev/demo/&quot;&gt;pgflow demo&lt;/a&gt; and provides both &lt;strong&gt;promise-based and event-based APIs&lt;/strong&gt; for starting workflows and monitoring real-time progress from TypeScript environments (browsers, Node.js, Deno, React Native).&lt;/p&gt;
&lt;p&gt;Features include &lt;strong&gt;type-safe flow management&lt;/strong&gt; with automatic inference from flow definitions, &lt;strong&gt;real-time progress monitoring&lt;/strong&gt; via Supabase broadcasts, and extensive test coverage.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Learn more:&lt;/strong&gt; &lt;a href=&quot;https://www.pgflow.dev/build/starting-flows/typescript-client/&quot;&gt;TypeScript Client Guide&lt;/a&gt; | &lt;a href=&quot;https://www.pgflow.dev/reference/pgflow-client/&quot;&gt;@pgflow/client API Reference&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;documentation-restructure-and-new-landing-page&quot;&gt;Documentation Restructure and New Landing Page&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The entire documentation has been reorganized from a feature-based structure to a
&lt;strong&gt;user-journey-based structure&lt;/strong&gt;, making it easier to find what you need at each stage of using pgflow.&lt;/p&gt;














&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Before&lt;/th&gt;&lt;th&gt;After&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;img src=&quot;https://www.pgflow.dev/_astro/docs-before.D6qo4fRL.png&quot; alt=&quot;Documentation structure before reorganization&quot;&gt;&lt;/td&gt;&lt;td&gt;&lt;img src=&quot;https://www.pgflow.dev/_astro/docs-after.DZe3mf5j.png&quot; alt=&quot;Documentation structure after reorganization&quot;&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;New documentation includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/build/&quot;&gt;Build section&lt;/a&gt; - Guides for starting flows, organizing code, processing arrays, and managing versions&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/deploy/&quot;&gt;Deploy section&lt;/a&gt; - Production deployment guides for Supabase&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/concepts/&quot;&gt;Concepts&lt;/a&gt; - Understanding map steps, context object, data model, and architecture&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pgflow.dev/reference/pgflow-client/&quot;&gt;@pgflow/client API Reference&lt;/a&gt; - Complete client library documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;redesigned-landing-page&quot;&gt;Redesigned Landing Page&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The homepage has been completely rebuilt with animated DAG visualization, interactive before/after code comparisons, and streamlined messaging. Visit &lt;a href=&quot;https://www.pgflow.dev/&quot;&gt;pgflow.dev&lt;/a&gt; to explore the new experience.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;developer-experience-improvements&quot;&gt;Developer Experience Improvements&lt;/h2&gt;&lt;/div&gt;

&lt;div&gt;&lt;div&gt;&lt;p&gt;&lt;strong&gt;Copy to Markdown on All Docs Pages&lt;/strong&gt; - Every documentation page now includes contextual menu buttons to copy the page as markdown or open it directly in Claude Code or ChatGPT for context-aware assistance.&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;starlight-image-zoom-zoomable&gt;&lt;img src=&quot;https://www.pgflow.dev/_astro/contextual-menu.CDB6IgUU.png&quot; alt=&quot;Contextual menu showing copy to markdown and open in AI options&quot;&gt;&lt;button aria-label=&quot;Zoom image: Contextual menu showing copy to markdown and open in AI options&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Additional improvements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Full deno.json Support&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;pgflow compile&lt;/code&gt; now uses &lt;code dir=&quot;auto&quot;&gt;--config&lt;/code&gt; flag for complete deno.json support&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fixed config.toml Corruption&lt;/strong&gt; - CLI no longer corrupts minimal config.toml files (thanks to &lt;a href=&quot;https://github.com/DecimalTurn&quot;&gt;@DecimalTurn&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better Type Inference&lt;/strong&gt; - Improved DSL type inference for &lt;code dir=&quot;auto&quot;&gt;.array()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;.map()&lt;/code&gt; methods&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compile-time Duplicate Slug Detection&lt;/strong&gt; - Prevents duplicate step slugs before deployment&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;reliability-improvements&quot;&gt;Reliability Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Enhanced Failure Handling&lt;/strong&gt; - Automatic archival of queued messages when runs fail, with stored output for debugging&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fixed Data Pruning Bug&lt;/strong&gt; - Resolved foreign key constraint issue preventing cleanup operations&lt;/li&gt;
&lt;li&gt;Comprehensive integration tests for map steps and enhanced type testing infrastructure&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;upgrading-to-070&quot;&gt;Upgrading to 0.7.0&lt;/h2&gt;&lt;/div&gt;
&lt;aside aria-label=&quot;Data Migration Included&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Data Migration Included &lt;/p&gt; &lt;div&gt; &lt;p&gt;This release includes automatic data migration that modifies existing &lt;code dir=&quot;auto&quot;&gt;step_states&lt;/code&gt; rows for map step support. For production environments, run the &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/blob/main/pkgs/core/queries/PRE_MIGRATION_CHECK_20251006073122.sql&quot;&gt;pre-migration check query&lt;/a&gt; to verify safety before upgrading.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;p&gt;See the &lt;a href=&quot;https://www.pgflow.dev/deploy/update-pgflow/&quot;&gt;update guide&lt;/a&gt; for complete instructions.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Questions or issues with the upgrade?&lt;/strong&gt; Join our &lt;a href=&quot;https://www.pgflow.dev/discord/&quot;&gt;Discord community&lt;/a&gt;
or &lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues&quot;&gt;open an issue on GitHub&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>release</category><category>map-steps</category><category>documentation</category><category>public-beta</category><category>core</category><category>dsl</category><category>cli</category><category>client</category></item><item><title>pgflow 0.6.1: Worker Configuration in Handler Context</title><link>https://www.pgflow.dev/news/pgflow-0-6-1-worker-config-in-handler-context/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-6-1-worker-config-in-handler-context/</guid><pubDate>Fri, 05 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;pgflow 0.6.1 adds &lt;code dir=&quot;auto&quot;&gt;workerConfig&lt;/code&gt; to the handler execution context, enabling intelligent decision-making based on worker configuration.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;worker-configuration-in-context&quot;&gt;Worker Configuration in Context&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Handlers now have access to the complete worker configuration through &lt;code dir=&quot;auto&quot;&gt;context.workerConfig&lt;/code&gt; (&lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/200&quot;&gt;#200&lt;/a&gt;). This enables smarter handlers that can adapt their behavior based on retry limits, concurrency settings, timeouts, and other worker parameters.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sendEmail&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;isLastAttempt&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;rawMessage&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;read_ct&lt;/span&gt;&lt;span&gt; &gt;= &lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;workerConfig&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;retry&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;limit&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (isLastAttempt) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// Use fallback email service on final attempt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sendWithFallbackProvider&lt;/span&gt;&lt;span&gt;(input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;subject&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// Use primary email service for regular attempts&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sendWithPrimaryProvider&lt;/span&gt;&lt;span&gt;(input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;subject&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;See the &lt;a href=&quot;https://www.pgflow.dev/reference/context/#workerconfig&quot;&gt;context documentation&lt;/a&gt; for complete details on available configuration properties and additional examples.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;bug-fix&quot;&gt;Bug Fix&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release also fixes retry strategy validation to only enforce the 50-limit cap for exponential retry strategy, allowing higher limits for fixed strategy when needed (&lt;a href=&quot;https://github.com/pgflow-dev/pgflow/issues/199&quot;&gt;#199&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;updating-to-061&quot;&gt;Updating to 0.6.1&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Follow our &lt;a href=&quot;https://www.pgflow.dev/deploy/update-pgflow/&quot;&gt;update guide&lt;/a&gt; for step-by-step upgrade instructions.&lt;/p&gt;</content:encoded><category>release</category><category>edge-worker</category><category>context</category><category>configuration</category></item><item><title>pgflow 0.6.0: Worker Deprecation and Context Changes</title><link>https://www.pgflow.dev/news/pgflow-0-6-0-worker-deprecation-and-context-changes/</link><guid isPermaLink="true">https://www.pgflow.dev/news/pgflow-0-6-0-worker-deprecation-and-context-changes/</guid><pubDate>Wed, 06 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;pgflow 0.6.0 introduces worker deprecation for deployments without version overlap and simplifies the context object with breaking changes.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;worker-deprecation&quot;&gt;Worker Deprecation&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Deploy new workers without version overlap. Deprecated workers stop accepting new tasks while finishing current work.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;-- Deprecate old workers before starting new ones&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;UPDATE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pgflow&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;workers&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SET&lt;/span&gt;&lt;span&gt; deprecated_at &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NOW&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; function_name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;your-worker-name&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;AND&lt;/span&gt;&lt;span&gt; deprecated_at &lt;/span&gt;&lt;span&gt;IS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Workers detect deprecation within 5 seconds via heartbeat and gracefully stop polling. The &lt;a href=&quot;https://www.pgflow.dev/deploy/supabase/update-deployed-flows/&quot;&gt;deployment guide&lt;/a&gt; has been simplified with a single safe deployment sequence.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;breaking-context-changes&quot;&gt;Breaking Context Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The context object is now cleaner and more consistent:&lt;/p&gt;
&lt;aside aria-label=&quot;Breaking Changes&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Breaking Changes &lt;/p&gt; &lt;div&gt; &lt;ul&gt;
&lt;li&gt;Removed: &lt;code dir=&quot;auto&quot;&gt;context.anonSupabase&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Renamed: &lt;code dir=&quot;auto&quot;&gt;context.serviceSupabase&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;context.supabase&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;p&gt;&lt;strong&gt;Before (0.5.x):&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const { &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt; } = await &lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;serviceSupabase&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;users&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;After (0.6.0):&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const { &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt; } = await &lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;supabase&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;users&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;migration&quot;&gt;Migration&lt;/h2&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Update context usage: &lt;code dir=&quot;auto&quot;&gt;context.serviceSupabase&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;context.supabase&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Remove any &lt;code dir=&quot;auto&quot;&gt;context.anonSupabase&lt;/code&gt; usage&lt;/li&gt;
&lt;li&gt;Use &lt;a href=&quot;https://www.pgflow.dev/deploy/supabase/update-deployed-flows/&quot;&gt;worker deprecation&lt;/a&gt; for smooth deployments&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The service role client is now the primary Supabase interface, simplifying database operations in handler functions.&lt;/p&gt;</content:encoded><category>release</category><category>edge-worker</category><category>deployment</category><category>context</category><category>breaking-change</category></item></channel></rss>