Skip to content

Realtime

Subscribe to run status changes and stream data from tasks to your frontend in real-time using SSE (Server-Sent Events).

Overview

Trigger.dev Realtime enables:

  • Live run status subscriptions
  • Streaming output from AI models
  • Progress updates with metadata
  • Multi-run monitoring

React Hooks

Install the React hooks package:

bash
npm i @trigger.dev/react-hooks

useRealtimeRun

Subscribe to a single run's status and output:

tsx
"use client";
import { useRealtimeRun } from "@trigger.dev/react-hooks";
import type { myTask } from "@/trigger/my-task";

export function RunStatus({ runId, accessToken }: { runId: string; accessToken: string }) {
  const { run, error } = useRealtimeRun<typeof myTask>(runId, {
    accessToken,
    onComplete: (run) => console.log("Done!", run.output),
  });

  if (error) return <div>Error: {error.message}</div>;
  if (!run) return <div>Loading...</div>;

  return (
    <div>
      <p>Status: {run.status}</p>
      {run.output && <p>Output: {JSON.stringify(run.output)}</p>}
    </div>
  );
}

useRealtimeRunsWithTag

Subscribe to all runs matching a tag:

tsx
import { useRealtimeRunsWithTag } from "@trigger.dev/react-hooks";

export function UserRuns({ userId, accessToken }: { userId: string; accessToken: string }) {
  const { runs } = useRealtimeRunsWithTag(`user_${userId}`, {
    accessToken,
  });

  return (
    <ul>
      {runs?.map(run => (
        <li key={run.id}>{run.status}</li>
      ))}
    </ul>
  );
}

useRealtimeBatch

Monitor all runs in a batch:

tsx
import { useRealtimeBatch } from "@trigger.dev/react-hooks";

export function BatchProgress({ batchId, accessToken }: { batchId: string; accessToken: string }) {
  const { runs } = useRealtimeBatch(batchId, { accessToken });

  const completed = runs?.filter(r => r.isCompleted).length ?? 0;
  const total = runs?.length ?? 0;

  return <div>{completed}/{total} complete</div>;
}

useRealtimeStream

Subscribe to a typed stream from a task:

tsx
import { useRealtimeStream } from "@trigger.dev/react-hooks";
import { aiStream } from "@/app/streams";

export function AIOutput({ runId, accessToken }: { runId: string; accessToken: string }) {
  const { parts, error } = useRealtimeStream(aiStream, runId, {
    accessToken,
    timeoutInSeconds: 600,
    throttleInMs: 50, // limit re-renders
  });

  return (
    <div>
      {parts?.map((part, i) => <span key={i}>{part}</span>)}
    </div>
  );
}

Backend Subscriptions

Use the SDK directly without React hooks:

ts
import { runs } from "@trigger.dev/sdk";

// Subscribe to a single run
for await (const run of runs.subscribeToRun(runId)) {
  console.log(run.status, run.output);
  if (run.isCompleted) break;
}

// Subscribe to runs by tag
for await (const run of runs.subscribeToRunsWithTag("user_123")) {
  console.log(run.id, run.status);
}

Access Tokens (Public)

Generate short-lived public access tokens for frontend clients — never expose your secret key:

ts
import { auth } from "@trigger.dev/sdk";

// In a server action or API route:
const publicToken = await auth.createPublicToken({
  scopes: {
    read: {
      runs: [runId],  // limit to specific runs
    },
  },
  expirationTime: "1h",
});

// Pass token to client
return { accessToken: publicToken };

Connection Limits

TierConcurrent connections
Free10
Hobby50
Pro500+

Extra: $10/month per 100 concurrent connections.

See Also

Built from official Trigger.dev documentation