Distributed systems fail in unpredictable ways. Network timeouts, partial failures, duplicate messages. Restate makes distributed code as reliable as local code — with automatic retries, state management, and exactly-once processing.
What Is Restate?
Restate is a durable execution engine. It intercepts your function calls, persists their state, and guarantees that every step completes exactly once — even across failures, restarts, and deployments. Think of it as Temporal, but lighter and easier to adopt.
The Free Platform
Restate is completely free and open source:
- Durable execution: Functions survive crashes and restarts
- Exactly-once: Each step executes exactly once
- Virtual objects: Stateful entities with built-in concurrency control
- Workflows: Long-running processes with human-in-the-loop
- Timers: Sleep for days/weeks without consuming resources
- SDKs: TypeScript, Java, Kotlin, Go, Rust, Python
- Self-hosted: Single binary, no dependencies
Quick Start
Install Restate:
brew install restatedev/tap/restate-server
restate-server
Write a durable function:
import * as restate from '@restatedev/restate-sdk';
const orderService = restate.service({
name: 'orders',
handlers: {
process: async (ctx: restate.Context, order: Order) => {
// Step 1: Reserve inventory (auto-retried on failure)
const reserved = await ctx.run('reserve', () =>
inventoryApi.reserve(order.items)
);
// Step 2: Charge payment
const payment = await ctx.run('charge', () =>
stripeApi.charge(order.customerId, order.total)
);
// Step 3: Wait for shipping (can sleep for days)
await ctx.sleep(24 * 60 * 60 * 1000); // 24 hours
// Step 4: Send tracking email
await ctx.run('notify', () =>
emailApi.sendTracking(order.email, payment.trackingId)
);
return { orderId: order.id, status: 'completed' };
},
},
});
restate.endpoint().bind(orderService).listen(9080);
Virtual objects (stateful entities):
const counter = restate.object({
name: 'counter',
handlers: {
add: async (ctx: restate.ObjectContext, value: number) => {
// State is automatically persisted
let count = (await ctx.get<number>('count')) ?? 0;
count += value;
ctx.set('count', count);
return count;
},
get: async (ctx: restate.ObjectSharedContext) => {
return (await ctx.get<number>('count')) ?? 0;
},
},
});
Call it:
# Register your service
restate deployments register http://localhost:9080
# Invoke
curl -X POST http://localhost:8080/orders/process \
-H 'Content-Type: application/json' \
-d '{"id": "ord_1", "items": ["item1"], "total": 4999}'
Why Teams Choose Restate
A food delivery app had a critical bug: when their payment service timed out mid-charge, the retry logic charged customers twice. Building idempotency keys and saga patterns took months. After switching to Restate, each step is automatically idempotent and exactly-once. Double charges went from 50/week to zero.
Who Is This For?
- Backend developers building payment flows, order processing, onboarding
- Teams needing Temporal-like durability without the operational complexity
- Serverless developers wanting durable functions beyond timeout limits
- Anyone building workflows that must complete reliably
Start Building Reliable Systems
Restate makes distributed code reliable by default. Write normal functions, get durable execution.
Need help with distributed systems? I build custom backend solutions — reach out to discuss your project.
Found this useful? I publish daily deep-dives into developer tools and APIs. Follow for more.
Top comments (0)