Workflow logs may contain sensitive data in the body or headers. Users need a way to redact these fields so they are not visible in the dashboard or API responses, preventing accidental data leaks. This also enables safer use of Workflow in multi-tenant setups where customer data may be included in logs.
Allow specifying fields to redact when triggering a workflow.
" });
const { workflowRunId } = await client.trigger({
url: "https://my-app.com/api/workflow",
body: { hello: "world" },
redact: {
body: true,
header: ["Authorization"] // or header: true to redact all headers
},
});">import { Client } from "@upstash/workflow";
const client = new Client({ token: "" });
const { workflowRunId } = await client.trigger({
url: "https://my-app.com/api/workflow",
body: { hello: "world" },
redact: {
body: true,
header: ["Authorization"] // or header: true to redact all headers
},
});
In this example, the log body and the "Authorization" header are redacted and will not appear in the UI or API responses. Instead, the UI will display REDACTED: so users can verify the value without revealing the original data.
This major version of the TypeScript SDK is done with breaking changes to improve the developer experience, reduce bundle size, and simplify configuration. We have prepared a migration guide for existing users below:
We currently provide a wait–notify mechanism that allows a workflow run to pause on an event ID and resume when a notify call is received. This works well when developers control both sides of the communication and can send the notification directly.
However, when a workflow needs to wait for a notification from a third-party provider, developers must register a waiter for a specific event ID, expose a custom endpoint to receive the third-party webhook, and then manually call our notify API with the event ID to resume the workflow. This process adds overhead and can lead to race conditions.
To improve the developer experience for webhook-based integrations and eliminate race conditions, we're introducing a new native webhook wait API. This API allows a workflow run to pause execution until an auto-generated webhook URL receives a notification. The generated URL can be passed directly to third-party providers, which will automatically notify the corresponding workflow run.
Each webhook can receive multiple notifications and be awaited multiple times.
Below is an early draft of the API (subject to change before release):
{
// 👇 Create a webhook to recieve events
const webhook = await context.createWebhook("fal-generation-webhook");
await context.run("start-generation", async () => {
const { request_id } = await fal.queue.submit("fal-ai/flux/dev", {
input: {
prompt: "a cat",
seed: 6252023,
image_size: "landscape_4_3",
num_images: 4,
},
// 👇 Pass webhook.url to third-party service
webhookUrl: webhook.url,
});
return request_id
});
// 👇 Wait for webhook to be called
const result = await context.waitForWebhook("wait-until-generation-completes", webhook, "1d");
await context.run("send-generation-to-user", async () => {
// 👇 result.timeout OR result.request
const req = result.request!;
// 👇 Use the native Request object of the webhook call
const data = await req.json();
console.log("Generation completed:", data.status);
});
} ); ">import { serve } from "@upstash/workflow/nextjs"; import { fal } from "@fal-ai/client";
export const { POST } = serve( async (context) => {
// 👇 Create a webhook to recieve events
const webhook = await context.createWebhook("fal-generation-webhook");
await context.run("start-generation", async () => {
const { request_id } = await fal.queue.submit("fal-ai/flux/dev", {
input: {
prompt: "a cat",
seed: 6252023,
image_size: "landscape_4_3",
num_images: 4,
},
// 👇 Pass webhook.url to third-party service
webhookUrl: webhook.url,
});
return request_id
});
// 👇 Wait for webhook to be called
const result = await context.waitForWebhook("wait-until-generation-completes", webhook, "1d");
await context.run("send-generation-to-user", async () => {
// 👇 result.timeout OR result.request
const req = result.request!;
// 👇 Use the native Request object of the webhook call
const data = await req.json();
console.log("Generation completed:", data.status);
});
} );
Remember last X triggers from the console so that it can be run again easily.
This is aimed for development purposes.
Add ability to list the flow-controls on the console together with their waitListSizes.
Make it searchable.
Add ability to restart or resume a workflow from the DLQ.
Restart : Ignore already completed steps and start the workflow from the beginning with the original body and headers.
Resume: Keep the completed steps and try to run the workflow starting from that point on.
See https://upstash.com/docs/workflow/features/dlq#recovery-actions
Workflow requires a publicly available API to send messages to. During development when applications are not yet deployed, developers typically need to expose their local API by creating a public tunnel. While local tunneling works seamlessly, it requires code changes between development and production environments and increase friction for developers. To simplify the development process, Upstash provides QStash CLI, which allows you to run a development server locally for testing and development.
With this work, the same UI that is given on the console.upstash.com can be used with local server(QStash CLI)
See https://upstash.com/docs/workflow/howto/local-development/development-server