Documentation Index
Fetch the complete documentation index at: https://docs.restate.dev/llms.txt
Use this file to discover all available pages before exploring further.
Restate provides three service types optimized for different use cases.
Service types comparison
| Basic Service | Virtual Object | Workflow |
| What | Independent stateless handlers | Stateful entity with a unique key | Multi-step processes that execute exactly-once per ID |
| State | None | Isolated per object key | Isolated per workflow instance |
| Concurrency | Unlimited parallel execution | Single writer per key (+ concurrent readers) | Single run handler per ID (+ concurrent signals/queries) |
| Key Features | Durable execution, service calls | Built-in K/V state, single-writer consistency | Durable promises, signals, lifecycle management |
| Best For | ETL, sagas, parallelization, background jobs | User accounts, shopping carts, agents, state machines, stateful event processing | Approvals, onboarding workflows, multi-step flows |
Basic Service
Basic Services group related handlers as callable endpoints.
const subscriptionService = restate.service({
name: "SubscriptionService",
handlers: {
add: async (ctx: restate.Context, req: SubscriptionRequest) => {
const paymentId = ctx.rand.uuidv4();
const payRef = await ctx.run(() =>
createRecurringPayment(req.creditCard, paymentId)
);
for (const subscription of req.subscriptions) {
await ctx.run(() =>
createSubscription(req.userId, subscription, payRef)
);
}
},
},
});
Characteristics:
- Use Durable Execution to run requests to completion
- Scale horizontally with high concurrency
- No shared state between requests
Use for: API calls, sagas, background jobs, task parallelization, ETL operations.
Virtual Object
Stateful entities identified by a unique key.
const cartObject = restate.object({
name: "ShoppingCart",
handlers: {
addItem: async (ctx: restate.ObjectContext, item: Item) => {
const items = (await ctx.get<Item[]>("cart")) ?? [];
items.push(item);
ctx.set("cart", items);
return items;
},
getTotal: restate.handlers.object.shared(
async (ctx: restate.ObjectSharedContext) => {
const items = (await ctx.get<Item[]>("cart")) ?? [];
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
),
},
});
Characteristics:
- Use Durable Execution to run requests to completion
- K/V state retained indefinitely and shared across requests
- Horizontal scaling with state consistency:
- At most one handler with write access can run at a time per object key. Mimicks a queue per object key.
- Concurrent execution across different object keys
- Concurrent execution of shared handlers (read-only)
Use for: Modeling entities like user accounts, shopping carts, chat sessions, AI agents, state machines, or any business entity needing persistent state.
Workflow
Workflows orchestrate multi-step processes with guaranteed once-per-ID execution.
const signupWorkflow = restate.workflow({
name: "UserSignup",
handlers: {
run: async (
ctx: restate.WorkflowContext,
user: { name: string; email: string }
) => {
// workflow ID = user ID; workflow runs once per user
const userId = ctx.key;
await ctx.run("create", () => createUserEntry({ userId, user }));
const secret = ctx.rand.uuidv4();
await ctx.run("mail", () => sendVerificationEmail({ user, secret }));
const clickSecret = await ctx.promise<string>("email-link-clicked");
return clickSecret === secret;
},
click: async (
ctx: restate.WorkflowSharedContext,
request: { secret: string }
) => {
await ctx.promise<string>("email-link-clicked").resolve(request.secret);
},
},
});
Characteristics:
- Use Durable Execution to run requests to completion
- The
run handler executes exactly once per workflow ID
- Other handlers run concurrently with the
run handler to signal, query state, or wait for events
- Optimized APIs for workflow interaction and lifecycle management
Use for: Processes requiring interaction capabilities like approval flows, user onboarding, multi-step transactions, and complex orchestration.
Choosing the right service type
Start with Basic Services for most business logic, data processing, and API integrations.
Use Virtual Objects to model stateful entities.
Use Workflows for multi-step processes that execute exactly-once and require interaction.
You can combine these service types within the same application for different aspects of your business logic.
Deployments, Endpoints, and Versions
Services deploy behind endpoints. Multiple services can bind to the same endpoint.
restate.serve({
services: [subscriptionService, cartObject, signupWorkflow],
port: 9080,
});
Services run on your preferred platform: serverless (AWS Lambda), containers (Kubernetes), or dedicated servers.
Restate handles versioning through immutable deployments where each deployment represents a specific, unchangeable version of your service code. After deploying your
services to an endpoint, you must register that endpoint with Restate so it can discover and route requests to it:
restate deployments register http://my-service:9080
When you update your services, you deploy the new version to a new endpoint and register it with Restate, which automatically routes new requests to the latest version while existing requests continue on their
original deployment until completion.
See deployment and versioning docs for details.