Creating Workflow Services
Guide to adding new Restate workflow services
Creating Workflow Services
When to Use Workflows
Use Restate workflows for operations that:
- ✅ Are long-running (seconds to hours)
- ✅ Need guaranteed completion despite failures
- ✅ Involve multiple external systems
- ✅ Must not run concurrently (use Virtual Objects)
Don't use workflows for:
- ❌ Simple CRUD operations
- ❌ Synchronous API calls
- ❌ Operations that complete in milliseconds
Steps
1. Define the Proto
Create go/proto/hydra/v1/yourservice.proto
:
Key decisions:
- Service type:
VIRTUAL_OBJECT
for serialization,SERVICE
otherwise - Key field: The field used for Virtual Object key (e.g.,
user_id
,project_id
)
2. Generate Code
3. Implement the Service
Create go/apps/ctrl/workflows/yourservice/
:
service.go:
your_operation_handler.go:
4. Register the Service
Update go/apps/ctrl/run.go
:
5. Call the Service
These are ugly, they're working on generating proper clients from the proto definitions https://github.com/restatedev/sdk-go/issues/103
Blocking call:
Fire-and-forget:
Best Practices
- Small Steps: Break operations into focused, single-purpose durable steps
- Named Steps: Always use
restate.WithName("step name")
for observability - Terminal Errors: Use
restate.TerminalError(err, statusCode)
for validation failures - Virtual Object Keys: Choose keys that represent the resource being protected
Examples
See existing implementations:
- DeploymentService:
go/apps/ctrl/workflows/deploy/
- RoutingService:
go/apps/ctrl/workflows/routing/
- CertificateService:
go/apps/ctrl/workflows/certificate/