# Workflows
_Path: en/concepts/workflows_
## Table of Contents
- Workflows
## Content
# Workflows
Workflows are durable, long-running operations that survive crashes and restarts. They provide reliability guarantees for critical business processes like payments, order fulfillment, and multi-step approvals.
## Why Workflows?
Functions are ephemeral - if the host crashes, in-flight work is lost. Workflows persist their state:
| Aspect | Functions | Workflows |
|--------|-----------|-----------|
| State | In memory | Persisted |
| Crash | Lost work | Resumes |
| Duration | Seconds to minutes | Hours to months |
| Completion | Best effort | Guaranteed |
## How Workflows Work
Workflow code looks like regular Lua code:
```lua
local funcs = require("funcs")
local time = require("time")
local result = funcs.call("app.api:charge_card", payment)
time.sleep("24h")
local status = funcs.call("app.api:check_status", result.id)
if status == "failed" then
funcs.call("app.api:refund", result.id)
end
```
The workflow engine intercepts calls and records results. If the process crashes, execution replays from history - same code, same results.
Wippy handles determinism automatically. Operations like funcs.call(), time.sleep(), uuid.v4(), and time.now() are intercepted and their results recorded. On replay, recorded values are returned instead of re-executing.
### Saga Pattern
Compensate on failure:
```lua
local funcs = require("funcs")
local inventory = funcs.call("app.inventory:reserve", items)
if inventory.error then
return nil, inventory.error
end
local payment = funcs.call("app.payments:charge", amount)
if payment.error then
funcs.call("app.inventory:release", inventory.id)
return nil, payment.error
end
local shipping = funcs.call("app.shipping:create", order)
if shipping.error then
funcs.call("app.payments:refund", payment.id)
funcs.call("app.inventory:release", inventory.id)
return nil, shipping.error
end
return {inventory = inventory, payment = payment, shipping = shipping}
```
### Waiting for Signals
Wait for external events (approval decisions, webhooks, user actions):
```lua
local funcs = require("funcs")
funcs.call("app.approvals:submit", request)
local inbox = process.inbox()
local msg = inbox:receive() -- blocks until signal arrives
if msg.approved then
funcs.call("app.orders:fulfill", request.order_id)
else
funcs.call("app.notifications:send_rejection", request)
end
```
## When to Use What
| Use Case | Choose |
|----------|--------|
| HTTP request handling | Functions |
| Data transformation | Functions |
| Background jobs | Processes |
| User session state | Processes |
| Real-time messaging | Processes |
| Payment processing | Workflows |
| Order fulfillment | Workflows |
| Multi-day approvals | Workflows |
## Starting Workflows
Workflows are spawned the same way as processes - using `process.spawn()` with a different host:
```lua
-- Spawn workflow on temporal worker
local pid = process.spawn("app.workflows:order_processor", "app:temporal_worker", order_data)
-- Send signals to workflow
process.send(pid, "update", {status = "approved"})
```
From the caller's perspective, the API is identical. The difference is the host: workflows run on a `temporal.worker` instead of a `process.host`.
When a workflow spawns children via process.spawn(), they become child workflows on the same provider, maintaining durability guarantees.
## Failure and Supervision
Processes can run as supervised services using `process.service`:
```yaml
# Process definition
- name: session_handler
kind: process.lua
source: file://session_handler.lua
method: main
# Supervised service wrapping the process
- name: session_manager
kind: process.service
process: app:session_handler
host: app:processes
lifecycle:
auto_start: true
restart:
max_attempts: 10
```
Workflows don't use supervision trees - they're automatically managed by the workflow provider (Temporal). The provider handles persistence, retries, and recovery.
## Configuration
Process definition (spawned dynamically):
```yaml
- name: order_processor
kind: workflow.lua
source: file://order_processor.lua
method: main
modules:
- funcs
- time
```
Workflow provider:
```yaml
- name: temporal_worker
kind: temporal.worker
client: app:temporal_client
task_queue: "orders"
lifecycle:
auto_start: true
```
See [Temporal](https://temporal.io) for production workflow infrastructure.
## See Also
- [Functions](concepts/functions.md) - Stateless request handling
- [Process Model](concepts/process-model.md) - Stateful background work
- [Supervision](guides/supervision.md) - Process restart policies
## Navigation
Previous: Functions (concepts/functions)
Next: Overview (lua/overview)