# Choose your approach

import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components';

pgflow workflows can be started from multiple places. Choose the approach that best fits your use case.

## Comparison

| Approach | Use When | Real-Time Updates | Complexity |
|----------|----------|-------------------|------------|
| [TypeScript Client](#typescript-client) | Building apps that show live progress to users | ✅ Built-in | Medium |
| [Supabase RPC](#supabase-rpc) | Simple fire-and-forget triggers from code | ⚠️ Via Client | Low |
| [pg_cron](#scheduled-tasks) | Running recurring tasks on a schedule | ⚠️ Via Client | Low |
| [Database Triggers](#event-driven) | Reacting automatically to data changes | ⚠️ Via Client | Medium |

:::tip
Flows started by **any method** can be monitored in real-time using the [TypeScript Client's `getRun()` method](/build/starting-flows/typescript-client/#retrieving-existing-runs). Only the TypeScript Client provides built-in real-time monitoring when starting flows.
:::

## TypeScript Client

Use `@pgflow/client` when building applications that need to stream real-time progress updates to users.

**Best for:**
- AI generation progress bars
- Multi-step workflow visualization
- Interactive dashboards
- Real-time status updates in browsers

```typescript
import { PgflowClient } from '@pgflow/client';

const pgflow = new PgflowClient(supabase);
const run = await pgflow.startFlow('process_video', { url });
run.on('*', (event) => console.log(event.status));
await run.waitForStatus('completed');
```

## Supabase RPC

Use [RPC calls](https://supabase.com/docs/reference/javascript/rpc) when you just need to trigger workflows without real-time updates.

**Best for:**
- Fire-and-forget workflows
- Simple background jobs

```typescript
await supabase.schema('pgflow').rpc('start_flow', {
  flow_slug: 'send_email',
  input: { to: 'user@example.com' }
});
```

## Scheduled Tasks

Use [pg_cron](https://supabase.com/docs/guides/cron) to run workflows on a recurring schedule.

**Best for:**
- Periodic data syncing
- Scheduled reports
- Cleanup tasks
- Time-based automation

```sql
SELECT cron.schedule(
  'daily-sync',
  '0 2 * * *',
  $$ SELECT pgflow.start_flow('sync_data', '{}') $$
);
```

## Event-Driven

Use database triggers to automatically start workflows when data changes.

**Best for:**
- Processing new records automatically
- Reacting to data changes

```sql
-- Trigger function starts a workflow for each new order
CREATE FUNCTION process_new_orders()
RETURNS TRIGGER AS $$
BEGIN
  PERFORM pgflow.start_flow(
    flow_slug => 'process_order',
    input => jsonb_build_object(
      'order_id', new_orders.id,
      'customer_id', new_orders.customer_id
    )
  )
  FROM new_orders;
  RETURN NULL;
END;
$$ LANGUAGE plpgsql;

-- Trigger fires once per INSERT statement
CREATE TRIGGER on_order_created
  AFTER INSERT ON orders
  REFERENCING NEW TABLE AS new_orders
  FOR EACH STATEMENT
  EXECUTE FUNCTION process_new_orders();
```

## Detailed Guides

<CardGrid>
  <LinkCard
    title="TypeScript Client"
    href="/build/starting-flows/typescript-client/"
    description="Full client library with real-time streaming and event subscriptions"
  />
  <LinkCard
    title="Supabase RPC"
    href="/build/starting-flows/supabase-rpc/"
    description="Simple RPC calls for fire-and-forget workflow triggering"
  />
  <LinkCard
    title="pg_cron"
    href="/build/starting-flows/pg-cron/"
    description="Run workflows on a recurring schedule with cron expressions"
  />
  <LinkCard
    title="Database Triggers"
    href="/build/starting-flows/database-triggers/"
    description="Automatically start workflows when database records change"
  />
</CardGrid>