Skip to main content

Async tasks

Flexible, durable scheduling across processes and time.

Restate lets you write resilient scheduling logic with the flexibility of code: delay execution, re-attach to ongoing tasks, fan-out/in patterns, and more. Restate guarantees that your tasks run to completion exactly once.

Async tasks

Durable timers
Persist timers in Restate. Restate makes sure that they get fired when they should, whether it's millis or months later.
(Delayed) task queue
Use Restate as message queue and schedule tasks asynchronously. Tasks execute with workflow-like durability and reliability. Restate handles retries and recovery of progress.
Switch between async and sync
Schedule an async task through Restate, then let any process latch onto it later to wait for the result or check its completion status, all with built-in durability.

Scheduling async tasks with Restate

Restate as message queue

Any function becomes a durable async task by using Restate as your message queue. Restate persists all requests and ensures they run to completion with automatic retries and recovery upon failures.

Learn more

Restate as message queue

Any function becomes a durable async task by using Restate as your message queue. Restate persists all requests and ensures they run to completion with automatic retries and recovery upon failures.

Learn more

Schedule async tasks

You can schedule tasks with the SDK clients or via HTTP, and you can postpone execution via the optional delay parameter.

Learn more

Schedule async tasks

You can schedule tasks with the SDK clients or via HTTP, and you can postpone execution via the optional delay parameter.

Learn more

Deduplicate requests

Use an idempotency key to ensure that the task is only scheduled once. For duplicate requests, Restate returns the previous response.

Deduplicate requests

Use an idempotency key to ensure that the task is only scheduled once. For duplicate requests, Restate returns the previous response.

Latch on to the task

Use the idempotency key to latch onto the task later and retrieve the result. You can also let another process latch on.

Learn more

Latch on to the task

Use the idempotency key to latch onto the task later and retrieve the result. You can also let another process latch on.

Learn more

const asyncTaskService = restate.service({
name: "taskWorker",
handlers: {
runTask: async (ctx: Context, params: TaskOpts) => {
return someHeavyWork(params);
},
},
});
export type AsyncTaskService = typeof asyncTaskService;
// The TypeScript SDK includes a client to send requests to services
const restateClient = restate.connect({ url: RESTATE_URL });
const taskHandle = await restateClient
.serviceSendClient<AsyncTaskService>({ name: "taskWorker" })
.runTask(
task,
SendOpts.from({ idempotencyKey: "dQw4w9WgXcQ", delay: 1000 })
);
// Attach to the async task to get the result
const result = await restateClient.result(taskHandle);

Restate as sophisticated task queue

Restate is built as an event-driven foundation, and therefore supports task queues by design.
Async tasks run like any other function in your infrastructure: on K8S, FaaS, or mix-and-match.
No need to spin up extra infrastructure or message queues.

Restate as sophisticated task queue

Parallelizing work with Restate

Fan out

Write flexible scheduling logic with Restate's durable building blocks. Fan out tasks with resilient RPC calls. Restate makes sure all tasks run to completion, with retries and recovery upon failures.

Fan out

Write flexible scheduling logic with Restate's durable building blocks. Fan out tasks with resilient RPC calls. Restate makes sure all tasks run to completion, with retries and recovery upon failures.

Fan in

Invocations produce durable promises that can be awaited and combined. These durable promises can be recovered on other processes after a failure.

Fan in

Invocations produce durable promises that can be awaited and combined. These durable promises can be recovered on other processes after a failure.

Server(less)

Deploy this service or its subtask processors on a platform like Kubernetes or AWS Lambda to automatically get parallel scale out.

Learn more

Server(less)

Deploy this service or its subtask processors on a platform like Kubernetes or AWS Lambda to automatically get parallel scale out.

Learn more

const workerService = restate.service({
name: "worker",
handlers: {
run: async (ctx: Context, task: Task) => {
// Split the task in subtasks
const subtasks: SubTask[] = await ctx.run("split task", () =>
split(task)
);
const resultPromises = [];
for (const subtask of subtasks) {
const subResultPromise = ctx
.serviceClient(workerService)
.runSubtask(subtask);
resultPromises.push(subResultPromise);
}
const results = await CombineablePromise.all(resultPromises);
return aggregate(results);
},
runSubtask: async (ctx: Context, subtask: SubTask) => {
// Processing logic goes here ...
// Can be moved to a separate service to scale independently
},
},
});
export const handler = restate.endpoint().bind(workerService).handler();
LOW-LATENCY

Restate’s event-driven foundation built in Rust lets you queue events. Restate pushes them to your functions at high speed.

Learn more

DURABLE EXECUTION

Restate guarantees all tasks run to completion. It keeps track of timers, handles retries and recovery upon failures, and ensures that tasks are executed exactly once.

Learn more

Durable webhook processing with Restate

Restate handlers as durable event processors

Point your webhook endpoint to any Restate handler. Restate makes sure all events are persisted and run to completion.

Restate handlers as durable event processors

Point your webhook endpoint to any Restate handler. Restate makes sure all events are persisted and run to completion.

Schedule follow-up tasks for webhook events, like reminders or escalations.

Schedule follow-up tasks for webhook events, like reminders or escalations.

Stateful handlers and event joins

Correlate or join asynchronous events by routing them to the same object.

Restate ensures sequential processing of events for the same key while giving access to durable key-value state.

Stateful handlers and event joins

Correlate or join asynchronous events by routing them to the same object.

Restate ensures sequential processing of events for the same key while giving access to durable key-value state.

const paymentTracker = restate.object({ // one instance per invoice id
name: "PaymentTracker",
handlers: {
// Stripe sends us webhook events for invoice payment attempts
onPaymentSuccess: async (ctx: restate.ObjectContext, event: StripeEvent) => {
ctx.set("paid", true);
},
onPaymentFailed: async (ctx: restate.ObjectContext, event: StripeEvent) => {
if (await ctx.get<boolean>("paid")) {
return;
}
const remindersCount = await ctx.get<number>("reminders_count") ?? 0;
if (remindersCount < 3) {
ctx.set("reminders_count", remindersCount + 1);
await ctx.run(() => sendReminderEmail(event));
// Schedule next reminder via a delayed self call
await ctx.objectSendClient(
PaymentTracker,
ctx.key, // this object's invoice id
{delay: 24 * 60 * 60 * 1000}
).onPaymentFailed(event);
} else {
await ctx.run(() => escalateToHuman(event));
}
},
}
})

What you can build with Async Tasks and Restate

(Delayed) task queue

A task queue that can handle both immediate and scheduled tasks. Restate makes sure task submissions are idempotent and that tasks run to completion exactly once. You can attach back to tasks to retrieve their result later.

Durable webhook event processing

A Restate handler can be the endpoint for a webhook. Restate makes sure the events are persisted and retried until they run till completion.

Complex task scheduling

An invoice payment tracker which correlates payment success events and failure events. Until a success event is received, each failure event generates up to 3 daily reminders and then escalates to support.

Payments: Combining sync & async responses

Issue an idempotent payment to Stripe and process the response. The payment provider either responds immediately or notifies us later via a webhook.

Building Durable-Promises-as-a-Service with Restate

Using Restate to build Promises/Futures as a service, that can be exposed to external clients and are durable across processes and failures..

Wondering about a specific use case?

Let’s brainstorm together on Discord or Slack.

Didn't see your use case?

💡 You can invoke any handler asynchronously, so have a look at the other use case pages for more inspiration.

Developer Resources

Docs: Invocations and Scheduling
Docs: Durable Timers
Need help?

Join the Restate Discord or Slack communities