Skip to content

Events & Pub/Sub

Ironflow provides a complete event-driven architecture with three primary capabilities:

  1. Trigger Events: Start recorded executions (durable workflows) and notify real-time subscribers. Events are permanent recorded facts.
  2. Topics: Broadcast messages between services without triggering workflows.
  3. Real-time Subscriptions: Monitor execution and business logic via WebSocket or ConnectRPC.

Architecture

Ironflow separates recorded execution from real-time distribution:

Event-Driven Architecture — events fork into the Function Layer (durable workflows) and Event Stream Layer (real-time distribution)

Key behavior: Events are published to the Event Stream immediately. This enables real-time dashboards and monitoring even if no functions are registered to handle the event.


Choosing the Right Method

MethodNamespaceTriggers Workflows?Use Case
emit()events:YesBusiness events like order.placed.
publish()topic:NoService-to-service messages or notifications.
invoke()N/AYesCalling one workflow from another (RPC style).

SDK Examples & Error Handling

import { createClient, ironflow, IronflowError } from "@ironflow/node";
const client = createClient({ apiKey: "ifkey_..." });
// 1. Emit — from anywhere (server, script, handler)
try {
const { runIds } = await client.emit("order.placed", { id: "123" });
// 2. Publish — from anywhere
await client.publish("notifications.email", { to: "user@example.com" });
} catch (err) {
if (err instanceof IronflowError) {
console.error(`Request failed: ${err.message} (Code: ${err.code})`);
}
}
// 3. Invoke — step primitive, only inside a function handler
export const orderHandler = ironflow.createFunction(
{ id: "order-handler", triggers: [{ event: "order.placed" }] },
async ({ step }) => {
// result is the typed return value of the target function
const result = await step.invoke("generate-pdf", { id: "123" });
return result;
},
);

In This Section