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_OBJECTfor serialization,SERVICEotherwise - 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
The Restate SDK now generates typed ingress clients from proto definitions. Use these for type-safe, clean service calls.
Setup - Create a helper method in your service:
Blocking call (Request):
Fire-and-forget (Send):
Benefits:
- Type-safe: Compile-time checking of requests/responses
- Discoverable: IDE autocomplete for all operations
- Cleaner: No manual service name strings or type parameters
- Maintainable: Refactors automatically when proto changes
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/