step.ext.waitForEvent()

Pause workflow execution until a specific event is received or a timeout is reached. This is an Inngest-specific step extension that enables event-driven, long-running workflows with human-in-the-loop processes or cross-workflow communication.

Signature

step.ext.waitForEvent(
  stepId: string,
  opts: { event: string; timeout: number | string | Date }
): Promise<ReceivedEvent | null>

Parameters

NameTypeDescription
stepIdstringUnique identifier for this step. Used for state persistence.
optsWaitOptionsConfiguration options. See WaitOptions below.

WaitOptions

PropertyTypeDescription
eventstringRequired. The event name to wait for.
timeoutnumber | string | DateRequired. Maximum time to wait. Can be milliseconds (number), duration string (e.g., "7d"), or a Date object.

Returns

Returns a promise that resolves to either:

  • ReceivedEvent - The event that was received
  • null - If the timeout was reached before an event arrived

ReceivedEvent

PropertyTypeDescription
dataRecord<string, unknown>Event payload data.
idstringUnique event identifier.
namestringEvent name.
tsnumberEvent timestamp in milliseconds.
vstring | undefinedEvent version identifier.

Examples

Wait for approval with timeout:

const workflow = client.workflow(
  { id: "document-approval" },
  async ({ input }, step) => {
    const document = await step.run("create-document", async () => {
      return await db.documents.create(input.data);
    });
    
    await step.run("notify-approver", async () => {
      return await sendEmail(document.approverId, "Please review");
    });
    
    // Wait up to 7 days for approval
    const approval = await step.ext.waitForEvent("wait-approval", {
      event: "document.approved",
      timeout: "7d",
    });
    
    if (approval === null) {
      // Timeout reached without approval
      await step.run("handle-timeout", async () => {
        return await markDocumentExpired(document.id);
      });
      return { status: "expired" };
    }
    
    await step.run("finalize-document", async () => {
      return await db.documents.approve(document.id);
    });
    
    return { status: "approved", approver: approval.data.userId };
  }
);

Payment confirmation workflow:

const workflow = client.workflow(
  { id: "payment-confirmation" },
  async ({ input }, step) => {
    const order = await step.run("create-order", async () => {
      return await createOrder(input.data);
    });
    
    // Wait for payment webhook
    const payment = await step.ext.waitForEvent("wait-payment", {
      event: "payment.completed",
      timeout: 3600000, // 1 hour in milliseconds
    });
    
    if (payment === null) {
      await step.run("cancel-order", async () => {
        return await cancelOrder(order.id);
      });
      return { status: "cancelled" };
    }
    
    await step.run("fulfill-order", async () => {
      return await fulfillOrder(order.id, payment.data);
    });
    
    return { status: "completed" };
  }
);