Restate provides durable execution primitives that make distributed systems resilient by default, without the operational overhead.

Resilient Orchestration

Build microservices that automatically recover from failures without losing progress:
export const orderService = restate.service({
  name: "OrderService",
  handlers: {
    process: async (ctx: restate.Context, order: Order) => {
      // Each step is automatically durable and resumable
      const paymentId = ctx.rand.uuidv4();

      await ctx.run(() => chargePayment(order.creditCard, paymentId));

      for (const item of order.items) {
        await ctx.run(() => reserveInventory(item.id, item.quantity));
      }
      return { success: true, paymentId };
    },
  },
});
  • Automatic recovery: Code resumes exactly where it left off after failures
  • Standard development: Write services like regular HTTP APIs
  • Resilient Sagas: Implement complex multi-step transactions with resilient rollback

Reliable Communication & Idempotency

Flexible communication patterns with strong delivery guarantees: Invocations
  • Zero message loss: All service communication is durably logged
  • Built-in retries: Automatic exponential backoff for transient failures
  • Scheduling: Delay messages for future processing
  • Request deduplication: Idempotency keys prevent duplicate processing
// Request-response: Wait for result
const payRef = await ctx.serviceClient(paymentService).charge(req);

// Fire-and-forget: Guaranteed delivery without waiting
ctx.serviceSendClient(emailService).emailTicket(req);

// Delayed execution: Schedule for later
ctx
.serviceSendClient(emailService)
.sendReminder(order, sendOpts({ delay: dayBefore(req.concertDate) }));

Durable Stateful Entities

Manage stateful entities without external databases or complex consistency mechanisms: Virtual Objects
  • Durable persistence: Application state survives crashes and deployments
  • Simple concurrency model: Single-writer semantics prevent consistency issues and race conditions
  • Horizontal scaling: Each object has its own message queue. Different entity keys process independently
  • Built-in querying: Access state via UI and APIs
export default restate.object({
name: "UserAccount",
handlers: {
updateBalance: async (ctx: restate.ObjectContext, amount: number) => {
const balance = (await ctx.get<number>("balance")) ?? 0;
const newBalance = balance + amount;

if (newBalance < 0) {
throw new TerminalError("Insufficient funds");
}

ctx.set("balance", newBalance);
return newBalance;
},

getBalance: shared(async (ctx: restate.ObjectSharedContext) => {
return (await ctx.get<number>("balance")) ?? 0;
}),
},
});

Operational simplicity

Reduce infrastructure complexity (no need for queues + state stores + schedulers, etc.). A single binary including everything you need. Application Structure

Key Orchestration Patterns

Comparison with Other Solutions

FeatureRestateTraditional Orchestration
InfrastructureSingle binary deploymentMessage brokers + workflow engines + state stores
Service CommunicationBuilt-in reliable messagingExternal message queues required
State ManagementIntegrated durable stateExternal state stores + locks
Failure RecoveryAutomatic progress recoveryManual checkpoint/restart logic
Deployment ModelStandard HTTP servicesStandard HTTP services
Development ExperienceRegular code + IDE supportRegular code + IDE support
ObservabilityBuilt-in UI & execution tracingManual setup

Getting Started

Ready to build resilient microservices with Restate? Here are your next steps:
Evaluating Restate and missing a feature? Contact us on Discord or Slack.