Skip to content

# Wojciech Majewski (@jumski)

5 posts by Wojciech Majewski (@jumski)

## pgflow 0.7.1: Fix pgmq 1.5.1 Version Conflict on New Supabase Projects

Oct 30, 2025 - 1 min read
Wojciech Majewski (@jumski)
Creator and Maintainer
Featured

pgflow 0.7.1 fixes installation failures on fresh Supabase projects caused by pgmq version mismatch.

Existing Projects Unaffected

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.

## The Bug

Section titled “The Bug”

Installing pgflow on new Supabase projects failed with:

    ERROR: extension "pgmq" has no installation script nor update path for version "1.4.4" (SQLSTATE 22023)At statement: 2CREATE EXTENSION IF NOT EXISTS "pgmq" WITH SCHEMA "pgmq" VERSION "1.4.4"

## Why It Happened

Section titled “Why It Happened”

Supabase upgraded to pgmq 1.5.1 in Postgres 17.6.1.016+ (supabase/postgres#1668). pgflow’s initial migration was pinned to version 1.4.4, which no longer exists in new Supabase instances.

## The Fix

Section titled “The Fix”

Removed the version constraint from pgmq extension creation. pgflow now uses whatever pgmq version Supabase provides (1.4.4, 1.5.1, or newer).

    CREATE EXTENSION IF NOT EXISTS "pgmq" WITH SCHEMA "pgmq" VERSION "1.4.4";CREATE EXTENSION IF NOT EXISTS "pgmq" WITH SCHEMA "pgmq";

## Credits

Section titled “Credits”

Thanks to @kallebysantos for reporting this issue!

## pgflow 0.7.0: Public Beta with Map Steps and Documentation Redesign

Oct 19, 2025 - 4 min read
Wojciech Majewski (@jumski)
Creator and Maintainer
Featured

pgflow 0.7.0 is here - a major milestone that brings parallel array processing, production-ready stability, and a complete documentation redesign.

## pgflow Enters Public Beta

Section titled “pgflow Enters Public Beta”

pgflow has transitioned from alpha to public beta. Core functionality is stable and reliable, with early adopters already running pgflow in production environments.

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.

See the project status page for production recommendations and known limitations.

## Map Steps

Section titled “Map Steps”

Map steps enable parallel array processing by automatically creating multiple tasks - one for each array element.

    import { Flow } from '@pgflow/dsl/supabase';
    const BatchProcessor = new Flow<string[]>({  slug: 'batch_processor',  maxAttempts: 3,})  .map(    { slug: 'processUrls' },    async (url) => {      // Each URL gets its own task with independent retry      return await scrapeWebpage(url);    }  );

Why this matters:

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.

This independent retry isolation makes flows more efficient and resilient. Each task has its own retry counter, timeout, and execution context.

Map steps handle edge cases automatically:

- Empty arrays complete immediately without creating tasks
- Type violations fail gracefully with stored output for debugging
- Results maintain array order regardless of completion sequence

Learn more: Map Steps and Process Arrays in Parallel

## Array Steps

Section titled “Array Steps”

The new `.array()` method provides compile-time type safety for array-returning handlers:

    // Enforces array return type at compile timeflow.array({ slug: 'items' }, () => [1, 2, 3]);  // Valid
    flow.array({ slug: 'invalid' }, () => 42);  // Compile error

Array steps are a semantic wrapper that makes intent clear and moves type errors from `.map()` to `.array()`. When a map step depends on a regular step that doesn’t return an array, the compiler catches it too - `.array()` just makes the error location more precise and the code intention explicit.

## TypeScript Client - Now Fully Documented

Section titled “TypeScript Client - Now Fully Documented”

The `@pgflow/client` package, initially released in v0.4.0 but never widely announced, now has complete documentation. This type-safe client powers the pgflow demo and provides both promise-based and event-based APIs for starting workflows and monitoring real-time progress from TypeScript environments (browsers, Node.js, Deno, React Native).

Features include type-safe flow management with automatic inference from flow definitions, real-time progress monitoring via Supabase broadcasts, and extensive test coverage.

Learn more: TypeScript Client Guide | @pgflow/client API Reference

## Documentation Restructure and New Landing Page

Section titled “Documentation Restructure and New Landing Page”

The entire documentation has been reorganized from a feature-based structure to a user-journey-based structure, making it easier to find what you need at each stage of using pgflow.

Before | After
--- | ---

New documentation includes:

- Build section - Guides for starting flows, organizing code, processing arrays, and managing versions
- Deploy section - Production deployment guides for Supabase
- Concepts - Understanding map steps, context object, data model, and architecture
- @pgflow/client API Reference - Complete client library documentation

### Redesigned Landing Page

Section titled “Redesigned Landing Page”

The homepage has been completely rebuilt with animated DAG visualization, interactive before/after code comparisons, and streamlined messaging. Visit pgflow.dev to explore the new experience.

## Developer Experience Improvements

Section titled “Developer Experience Improvements”

Copy to Markdown on All Docs Pages - 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.

Additional improvements:

- Full deno.json Support - `pgflow compile` now uses `--config` flag for complete deno.json support
- Fixed config.toml Corruption - CLI no longer corrupts minimal config.toml files (thanks to @DecimalTurn)
- Better Type Inference - Improved DSL type inference for `.array()` and `.map()` methods
- Compile-time Duplicate Slug Detection - Prevents duplicate step slugs before deployment

## Reliability Improvements

Section titled “Reliability Improvements”

- Enhanced Failure Handling - Automatic archival of queued messages when runs fail, with stored output for debugging
- Fixed Data Pruning Bug - Resolved foreign key constraint issue preventing cleanup operations
- Comprehensive integration tests for map steps and enhanced type testing infrastructure

## Upgrading to 0.7.0

Section titled “Upgrading to 0.7.0”

Data Migration Included

This release includes automatic data migration that modifies existing `step_states` rows for map step support. For production environments, run the pre-migration check query to verify safety before upgrading.

See the update guide for complete instructions.

Questions or issues with the upgrade? Join our Discord community or open an issue on GitHub.

## pgflow 0.6.1: Worker Configuration in Handler Context

Sep 5, 2025 - 1 min read
Wojciech Majewski (@jumski)
Creator and Maintainer

pgflow 0.6.1 adds `workerConfig` to the handler execution context, enabling intelligent decision-making based on worker configuration.

## Worker Configuration in Context

Section titled “Worker Configuration in Context”

Handlers now have access to the complete worker configuration through `context.workerConfig` (#200). This enables smarter handlers that can adapt their behavior based on retry limits, concurrency settings, timeouts, and other worker parameters.

    async function sendEmail(input, context) {  const isLastAttempt = context.rawMessage.read_ct >= context.workerConfig.retry.limit;
      if (isLastAttempt) {    // Use fallback email service on final attempt    return await sendWithFallbackProvider(input.to, input.subject, input.body);  }
      // Use primary email service for regular attempts  return await sendWithPrimaryProvider(input.to, input.subject, input.body);}

See the context documentation for complete details on available configuration properties and additional examples.

## Bug Fix

Section titled “Bug Fix”

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 (#199).

## Updating to 0.6.1

Section titled “Updating to 0.6.1”

Follow our update guide for step-by-step upgrade instructions.

## pgflow 0.6.0: Worker Deprecation and Context Changes

Aug 6, 2025 - 1 min read
Wojciech Majewski (@jumski)
Creator and Maintainer

pgflow 0.6.0 introduces worker deprecation for deployments without version overlap and simplifies the context object with breaking changes.

## Worker Deprecation

Section titled “Worker Deprecation”

Deploy new workers without version overlap. Deprecated workers stop accepting new tasks while finishing current work.

    -- Deprecate old workers before starting new onesUPDATE pgflow.workersSET deprecated_at = NOW()WHERE function_name = 'your-worker-name'  AND deprecated_at IS NULL;

Workers detect deprecation within 5 seconds via heartbeat and gracefully stop polling. The deployment guide has been simplified with a single safe deployment sequence.

## Breaking Context Changes

Section titled “Breaking Context Changes”

The context object is now cleaner and more consistent:

Breaking Changes

- Removed: `context.anonSupabase`
- Renamed: `context.serviceSupabase` → `context.supabase`

Before (0.5.x):

    async function handler(input, context) {  const { data } = await context.serviceSupabase    .from('users')    .select('*');}

After (0.6.0):

    async function handler(input, context) {  const { data } = await context.supabase    .from('users')    .select('*');}

## Migration

Section titled “Migration”

1. Update context usage: `context.serviceSupabase` → `context.supabase`
2. Remove any `context.anonSupabase` usage
3. Use worker deprecation for smooth deployments

The service role client is now the primary Supabase interface, simplifying database operations in handler functions.

## pgflow 0.5.4: Context - Simplify Your Handler Functions

Jul 17, 2025 - 2 min read
Wojciech Majewski (@jumski)
Creator and Maintainer

API Change in v0.6.0

Breaking Change: Starting with pgflow v0.6.0, the context API has been simplified. The `anonSupabase` and `serviceSupabase` clients have been replaced with a single `supabase` client (initialized with service role key).

If you’re using v0.6.0 or later, replace any usage of `ctx.anonSupabase` or `ctx.serviceSupabase` with `ctx.supabase`.

Workers now pass a context object as a second parameter to all handlers, providing ready-to-use database connections, environment variables, and Supabase clients.

## The Problem We Solved

Section titled “The Problem We Solved”

Previously, handlers relied on global singletons or manual resource initialization:

    // Before: Global resources that complicated testing and lifecycle managementimport { sql } from '../db.js';import { supabase } from '../supabase-client.js';
    // After: Clean dependency injection via contextasync function processPayment(input, ctx) {  const [payment] = await ctx.sql`    SELECT * FROM payments WHERE id = ${input.paymentId}  `;  await ctx.serviceSupabase.from('audit_logs').insert({    action: 'payment_processed',    payment_id: input.paymentId  });}

## What’s in the Context

Section titled “What’s in the Context”

Core resources (always available):

- `env` - Environment variables
- `shutdownSignal` - AbortSignal for graceful shutdown
- `rawMessage` - pgmq message metadata (msg_id, read_ct, etc.)
- `stepTask` - Step execution details (flows only)

Supabase resources:

- `sql` - PostgreSQL client (postgres.js)
- `anonSupabase` - Client with anon key (respects RLS)
- `serviceSupabase` - Client with service role (bypasses RLS)

## Key Benefits

Section titled “Key Benefits”

1. Zero Configuration - No connection boilerplate
2. Managed Resources - pgflow handles pooling and lifecycle
3. Type Safety - Full TypeScript support
4. Testable - Mock only what you use:

    // Handler uses only env? Test with only env:await handler(input, { env: { API_KEY: 'test' } });

## Migration

Section titled “Migration”

Existing handlers continue to work. Add the context parameter when you need platform resources:

    // Old handlers work fineasync function handler(input) { return { ok: true }; }
    // New handlers get contextasync function handler(input, ctx) {  const data = await ctx.sql`SELECT * FROM table`;  return { ok: true, count: data.length };}

This is Just the Beginning

Context is how pgflow manages resources. Soon you’ll define your own resources (OpenAI, Stripe, Redis, helpers) and access them the same way. Start using context now to be ready.

Updated packages: `@pgflow/edge-worker` and `@pgflow/dsl`