Skip to content

Bug: maxPgConnections config option is ignored in EdgeWorker.start() #588

@jumski

Description

@jumski

Description

The maxPgConnections option passed to EdgeWorker.start() is silently ignored. The SQL connection pool is always created with hardcoded max: 10 regardless of user configuration.

Reproduction

// User expects 4 connections per worker
EdgeWorker.start(GreetUser, { maxPgConnections: 4 });

// But each worker actually creates 10 connections
// With 8 workers: 80 connections instead of expected 32

Root Cause

The issue is in how the SQL client flows through the initialization:

  1. EdgeWorker.startFlowWorker() calls createAdapter() without passing maxPgConnections:

    // EdgeWorker.ts:197-200
    const platform = await createAdapter({
      sql: config.sql,
      connectionString: config.connectionString,
      // maxPgConnections is NOT passed here
    });
  2. SupabasePlatformAdapter creates SQL via resolveSqlConnection() with hardcoded max: 10:

    // resolveConnection.ts:87, 92, 97
    return postgres(options.connectionString, { prepare: false, max: 10 });
  3. EdgeWorker.startFlowWorker() passes platform's SQL to createFlowWorker:

    // EdgeWorker.ts:204-208
    const workerConfig: FlowWorkerConfig = {
      ...config,                           // maxPgConnections: 4 is here
      sql: platform.platformResources.sql, // BUT sql is overwritten with max:10 client
    };
  4. createFlowWorker() sees config.sql exists and uses it directly, never checking maxPgConnections:

    // createFlowWorker.ts:71-76
    const sql =
      config.sql ||  // ← truthy (platform SQL with max:10), so used directly
      postgres(config.connectionString, {
        max: config.maxPgConnections ?? 4,  // ← NEVER REACHED
      });

Impact

  • Users cannot control connection pool size
  • With default max: 10 and multiple workers, connection limits are easily exhausted
  • Results in CONNECTION_CLOSED errors and remaining connection slots are reserved for roles with SUPERUSER attribute errors

Proposed Fix

Option A (minimal): Pass maxPgConnections through to resolveSqlConnection():

// resolveConnection.ts - add maxPgConnections parameter
export function resolveSqlConnection(
  env: ConnectionEnv,
  options?: SqlConnectionOptions & { maxPgConnections?: number }
): postgres.Sql {
  const max = options?.maxPgConnections ?? 4;
  
  if (options?.sql) return options.sql;
  if (options?.connectionString) {
    return postgres(options.connectionString, { prepare: false, max });
  }
  // ... etc
}

And update createAdapter() to accept and pass through maxPgConnections.

Option B (cleaner): Don't create SQL in the platform adapter. Let createFlowWorker always create its own SQL connection using the config, and just pass connectionString from the platform.

Environment

  • @pgflow/edge-worker (current main branch)
  • Discovered while running 8 edge function workers with maxPgConnections: 4 config

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions