- Build durable, fault-tolerant service orchestrations with automatic failure recovery
- Implement sagas for distributed transactions with resilient compensation
- Use durable timers and external events for complex async patterns
- Implement stateful entities with Virtual Objects
Getting Started
A Restate application is composed of two main components:- Restate Server: The core engine that manages durable execution and orchestrates services. It acts as a message broker or reverse proxy in front of your services.
- Your Services: Your business logic, implemented as service handlers using the Restate SDK to perform durable operations.

Context
object that provides durable execution primitives. Any action performed with the Context is automatically recorded and can survive failures.
You don’t need to run your services in any special way. Restate works with how you already deploy your code, whether that’s in Docker, on Kubernetes, or via AWS Lambda.
Run the example
Install Restate and launch it:
Durable Execution
Restate uses Durable Execution to ensure your orchestration logic survives failures and restarts. Whenever a handler executes an action with the RestateContext
, this gets send over to the Restate Server and persisted in a log.
On a failure or a crash, the Restate Server sends a retry request that contains the log of the actions that were executed so far.
The service then replays the log to restore state and continues executing the remaining actions.
This process continues until the handler runs till completion.

- Context
run
actions make external calls or non-deterministic operations durable. They get replayed on failures. - If the service crashes after payment creation, it resumes at the subscription step
- Deterministic IDs logged with the context ensure operations are idempotent
- Full execution traces for debugging and monitoring
Try out Durable Execution
Try out Durable Execution
Once you restart the service, the workflow finishes successfully:

Error Handling
By default, Restate retries failures infinitely with an exponential backoff strategy. For some failures, you might not want to retry or only retry a limited number of times. For these cases, Restate distinguishes between two types of errors:- Transient Errors: These are temporary issues that can be retried, such as network timeouts or service unavailability. Restate automatically retries these errors.
- Terminal Errors: These indicate a failure that will not be retried, such as invalid input or business logic violations. Restate stops execution and allows you to handle these errors gracefully.
Configuring Retry Behavior
Configuring Retry Behavior
Some actions let you configure their retry behavior, for example to limit the number of retries of a run block:When the retries are exhausted, the run block will throw a
TerminalError
, that you can handle in your handler logic.Sagas and Rollback
On a terminal failure, Restate stops the execution of the handler. You might, however, want to roll back the changes made by the workflow to keep your system in a consistent state. This is where Sagas come in. Sagas are a pattern for rolling back changes made by a handler when it fails. In Restate, you can implement a saga by building a list of compensating actions for each step of the workflow. On a terminal failure, you execute them in reverse order: Benefits with Restate:- The list of compensations can be recovered after a crash, and Restate knows which compensations still need to be run.
- Sagas always run till completion (success or complete rollback)
- Full trace of all operations and compensations
- No complex state machines needed
Try out sagas
Try out sagas
Add a subscription for Disney:The Disney subscription is not available, so the handler will fail and run compensations:

Virtual Objects
Until now, the services we looked at did not share any state between requests. To implement stateful entities like shopping carts, user profiles, or AI agents, Restate provides Virtual Objects. Each Virtual Object instance maintains isolated state and is identified by a unique key. Here is an example of a Virtual Object that tracks user subscriptions:
- Long-lived state: K/V state is stored permanently. It has no automatic expiry. Clear it via
ctx.clear()
. - Durable state changes: State changes are logged with Durable Execution, so they survive failures and are consistent with code execution
- State is queryable via the state tab in the UI:
- Built-in concurrency control: Restate’s Virtual Objects have built-in queuing and consistency guarantees per object key. Handlers either have read-write access (
ObjectContext
) or read-only access (shared object context).- Only one handler with write access can run at a time per object key to prevent concurrent/lost writes or race conditions.
- Handlers with read-only access can run concurrently to the write-access handlers.

Try out Virtual Objects
Try out Virtual Objects
Add a few subscriptions for some users.
To call a Virtual Object, you specify the object key in the URL (here
user-123
and user-456
):Or use the UI’s state tab to explore the object state.Resilient Communication
The Restate SDK includes clients to call other handlers reliably. You can call another handler in three ways:- Request-Response: Wait for a response
- One-Way Messages: Fire-and-forget
- Delayed Messages: Schedule for later
Try out resilient communication
Try out resilient communication
Buy a concert ticket:See in the UI how the first call had the response logged, while the ticket delivery happened asynchronously and the reminder was scheduled for in 406 days:

Request Idempotency
Restate allows adding an idempotency header to your requests. It will then deduplicate requests with the same idempotency key, ensuring that they only execute once. This can help us prevent duplicate calls the concert ticketing service if the user accidentally clicks “buy” multiple times. Add an idempotency header to your request: Notice how doing the same request with the same idempotency key will print the same payment reference. Instead of executing the handler again, Restate returns the result of the first execution.External Events
Until now we showed either synchronous API calls viarun
or calls to other Restate services.
Another common scenario is APIs that respond asynchronously via webhooks or callbacks.
For this, you can use Restate’s awakeables.
For example, some payment providers like Stripe require you to initiate a payment and then wait for their webhook to confirm the transaction.
Awakeables are like promises or futures that can be recovered after a crash.
Restate persists the awakeable in its log and can recover it on another process when needed.
There is no limit to how long you can persist an awakeable, so you can wait for external events that may take hours, or even months to arrive.
You can also use awakeables to implement human-in-the-loop interactions, such as waiting for user input or approvals.
Try out external events
Try out external events
Initiate a payment by calling the 
process
handler. Add /send
to call the handler without waiting for the response:In the UI, you can see that the payment is waiting for confirmation.You can restart the service to see how Restate continues waiting for the payment confirmation.Simulate approving the payment by executing the curl request that was printed in the service logs, similar to:You can see in the UI that the payment was processed successfully and the awakeable was resolved:
Durable Timers
Waiting on external events might take a long time, and you might want to add timeouts to operations like this. The Restate SDK offers durable timer implementations that you can use to limit waiting for an action. Restate tracks these timers so they survive crashes and do not restart from the beginning. Let’s extend our payment service to automatically cancel payments that don’t complete within a reasonable time: You can also set timeouts for RPC calls or other asynchronous operations with the Restate SDK.Try out durable timers
Try out durable timers
Initiate a payment by calling the 
process
handler. Add /send
to call the handler without waiting for the response:Wait for 30 seconds without confirming the payment.Try restarting the service while the payment is waiting for confirmation to see how Restate continues waiting for the timer and the confirmation.In the UI, you can see that the payment times out and cancels the payment:
Concurrent Tasks
When you are waiting on an awakeable or a timer, you are effectively running concurrent tasks and waiting for one of them to complete. Restate allows more advanced concurrency patterns to run tasks in parallel and wait for their results. Let’s extend our subscription service to process all subscriptions concurrently and handle failures gracefully: Restate retries all parallel tasks until they all complete and can deterministically replay the order of completion.Try out concurrent tasks
Try out concurrent tasks
Add a few subscriptions for some users.In the UI, you can see that all subscriptions are processed in parallel:

Summary
Restate simplifies microservice orchestration with:- Durable Execution: Automatic failure recovery without complex retry logic
- Sagas: Distributed transactions with resilient compensation
- Service Communication: Reliable RPC and messaging between services
- Stateful Processing: Consistent state management without external stores
- Advanced Patterns: Fault-tolerant timers, awakeables, and parallel execution