pgflow vs Trigger.dev
Features
Section titled “Features”Technical Criteria | pgflow | Trigger.dev |
---|---|---|
Architecture Model | Database-centric orchestration | Background job execution and orchestration |
Infrastructure Requirements | Zero additional (just Supabase) | Hosted service with dashboard or self-hosted |
Workflow Definition | TypeScript DSL with explicit dependencies | TypeScript functions with tasks and subtasks |
Supabase Integration | Built-in | Requires manual configuration |
Type System | End-to-end type safety | Standard TypeScript typing |
Failure Handling | Automatic per-step retries | Configurable per-task retries |
Event Handling | No explicit hooks | Rich hooks (init, cleanup, onSuccess, onFailure) |
Developer Experience | DSL-based API | Function-based API with lifecycle hooks |
Maturity Level | Active development | Production-ready |
Monitoring Tools | SQL queries for visibility | Comprehensive web dashboard |
Execution Structure | Database-driven DAG | Task/subtask hierarchy |
Concurrency Management | Simple per-flow limits | Advanced queues and limits |
Scheduling Capabilities | Built into Supabase (pg_cron) | Built-in cron scheduler |
Both systems provide reliable task execution with proper retries and error handling. The key difference is who controls the workflow orchestration: the database (pgflow) or the task execution platform (Trigger.dev).
When to Choose
Section titled “When to Choose”pgflow
Section titled “pgflow”- Committed to Supabase - Want a workflow solution that lives entirely inside your Supabase project
- DAG-based workflows - Need to express complex data dependencies as a directed acyclic graph
- SQL visibility - Prefer direct database access to monitor workflow state via SQL queries
- Lightweight deployment - Need minimal infrastructure with no additional services to maintain
- PostgreSQL transactions - Want to leverage database transactions throughout workflows
- Edge Function execution - Want to run workflow steps as Supabase Edge Functions
- Explicit data flow - Prefer declarative data dependencies over imperative control flow
Trigger.dev
Section titled “Trigger.dev”- User-friendly dashboard - Need comprehensive UI for monitoring and managing workflow runs
- Task relationships - Prefer parent-child task relationships over explicit dependency graphs
- Advanced concurrency - Need sophisticated queuing with per-tenant concurrency controls
- Rich lifecycle hooks - Want init, cleanup, onSuccess, and onFailure lifecycle hooks
- Delay capabilities - Need to schedule tasks for future execution with precise timing
- Framework integration - Desire tight integration with Next.js and other frameworks
- Immediate production use - Need a mature, battle-tested solution ready for production
Code Examples
Section titled “Code Examples”pgflow
Section titled “pgflow”pgflow puts PostgreSQL at the center of your workflow orchestration. Workflows are defined in TypeScript but compiled to SQL migrations with all orchestration logic running directly in the database. The database decides when tasks are ready to execute based on explicit dependencies.
// In pgflow, the database orchestrates the workflownew Flow<{ url: string }>({ slug: 'analyze_website',}) .step( { slug: 'extract' }, async (input) => /* extract data */ ) .step( { slug: 'transform', dependsOn: ['extract'] }, async (input) => /* transform using extract results */ );
Trigger.dev
Section titled “Trigger.dev”Trigger.dev provides a task-based system where you define individual tasks with explicit handlers and lifecycle hooks. Tasks can be triggered manually or from other tasks.
// In Trigger.dev, you define tasks with handlers and hooksimport { task } from "@trigger.dev/sdk/v3";
export const extractData = task({ id: "extract-data", // Optional initialization hook init: async (payload) => { return { client: createApiClient() }; }, run: async (payload: { url: string }, { init }) => { // Use resources from init return await init.client.fetch(payload.url); }});
// Parent task that coordinates workflowexport const analyzeWebsite = task({ id: "analyze-website", run: async (payload: { url: string }) => { // Extract data and wait for result const data = await extractData.triggerAndWait({ url: payload.url }).unwrap();
// Process data and return result return processData(data); }});
Similarities
Section titled “Similarities”Both systems provide reliable execution of workflow tasks:
- Both can properly handle retries and error recovery
- Both track execution state and progress
- Both provide typing and type safety
- Both support parallel execution of independent tasks
- Both allow the scheduling/triggering of workflow execution
The difference is architectural:
- pgflow: PostgreSQL orchestrates when steps run based on dependencies
- Trigger.dev: Platform manages task execution with flexible triggering options
Integration with Supabase
Section titled “Integration with Supabase”pgflow
Section titled “pgflow”- Native integration - Built specifically for Supabase ecosystem
- Zero infrastructure - Uses Supabase Edge Functions and PostgreSQL
- Simple setup - Single command (
npx pgflow install
) sets up all required components - Direct database access - All workflow state directly accessible in your Supabase database
Trigger.dev
Section titled “Trigger.dev”- Possible integration - Can work with Supabase but not specifically designed for it
- Additional infrastructure - Requires either hosted service or self-hosted instance
- Connection - Requires connecting Supabase to Trigger.dev infrastructure
- Separate dashboard - Uses its own dashboard for monitoring and management