workflow
Version:
Workflow SDK - Build durable, resilient, and observable workflows
134 lines (82 loc) • 6.56 kB
text/mdx
title: Local World
description: Zero-config world bundled with Workflow for local development. No external services required.
type: integration
summary: Set up the Local World for zero-configuration workflow development on your machine.
prerequisites:
- /docs/deploying
related:
- /worlds/postgres
- /worlds/vercel
The Local World is bundled with `workflow` and used automatically during local development. It requires no installation or configuration.
To explicitly use the Local World in any environment, set this environment variable:
```bash
WORKFLOW_TARGET_WORLD=local
```
## Observability
The Workflow CLI uses the Local World by default. Run these commands inside your workflow project to view your local development workflows:
```bash
# List recent workflow runs
npx workflow inspect runs
# Launch the web UI
npx workflow web
```
Learn more in the [Observability](/docs/observability) documentation.
## Testing & compatibility
<WorldTestingPerformance worldId="local" />
## Configuration
The Local World requires no configuration, but you can customize its behavior through environment variables or programmatically through `createWorld()`.
### `WORKFLOW_LOCAL_DATA_DIR`
Directory for storing workflow data as JSON files. Default: `.workflow-data/`
### `PORT`
The application dev server port. Used to deliver workflow queue messages to the combined flow route. Default: auto-detected
### `WORKFLOW_LOCAL_BASE_URL`
Full base URL override for HTTPS or custom hostnames. Default: `http://localhost:{port}`
Port resolution priority: `baseUrl` > `port` > `PORT` > auto-detected
### `WORKFLOW_LOCAL_QUEUE_CONCURRENCY`
Maximum number of concurrent queue message handlers. Default: `1000`
### `WORKFLOW_LOCAL_QUEUE_MAX_VISIBILITY`
Maximum number of seconds a local queue message can stay hidden before the handler rechecks the run. Default: unlimited.
### `WORKFLOW_LOCAL_RUN_STATUS_POLL_INTERVAL_MS`
How often a wait for a terminal run status re-reads the run file, in milliseconds. Default: `100`.
`await run.returnValue` asks the World to wait for the run to finish. When the run and the caller share a process (the usual development server case), an in-process signal resolves the wait as soon as the run ends, and this interval never comes into play. The interval covers activity the signal cannot detect, primarily a second process awaiting a run over the same data directory, so it is set far below Workflow's own polling interval.
### `WORKFLOW_LOCAL_HEADERS_TIMEOUT_MS`
Maximum time in milliseconds to wait for a local queue handler to begin responding before redelivering the durable message. Default: `0` (no deadline).
A delivery executes inline steps before the handler responds, so a deadline shorter than your longest step redelivers a healthy delivery while it is still running and executes the same step again. Set this only if you would rather a hung handler be redelivered, and set it above the longest inline work you expect.
### `WORKFLOW_LOCAL_BODY_TIMEOUT_MS`
Maximum gap in milliseconds between response body chunks from a local queue handler before redelivering the durable message. Default: `0` (no deadline). The same caution as `WORKFLOW_LOCAL_HEADERS_TIMEOUT_MS` applies.
### `WORKFLOW_NODE_HTTP`
Whether queue deliveries go out through Node's built-in `node:http` and `node:https` modules instead of the HTTP client library this World normally uses. Default: disabled. Set to `1` to switch to Node's modules. Socket pooling, keep-alive, and both timeouts above apply either way. See [`WORKFLOW_NODE_HTTP`](/docs/configuration/runtime-tuning#workflow_node_http) for what else changes.
### `WORKFLOW_LOCAL_RECOVER_ACTIVE_RUNS`
Whether pending and running runs found in the data directory are re-enqueued when the World starts. Set to `0` or `false` to skip recovery and leave stale runs untouched. Default: `true`.
### `WORKFLOW_LOCAL_HOOK_RETENTION_LIMIT_DAYS`
Maximum [`experimental_minRetention`](/docs/api-reference/workflow/create-hook#keep-a-token-unavailable-after-the-run-ends) accepted by the Local World, in days. Default: `30`. Set this to the same limit as your production World so oversized values fail during local development.
### `WORKFLOW_STREAM_FLUSH_INTERVAL_MS`
Group-commit window, in milliseconds, for the leading chunk of an idle stream. Default: `0` (dispatch immediately). A positive value holds the first chunk up to that long to collect a group, trading first-chunk latency for fewer requests. Chunks arriving while a request is in flight always coalesce into the next group regardless.
### Programmatic configuration
Options passed to `createWorld()` take precedence over the environment variables above. Export the configured World from a module and point `WORKFLOW_TARGET_WORLD` at that module:
```typescript title="my-world.ts" lineNumbers
import { createWorld } from "@workflow/world-local";
export default createWorld({
dataDir: "./custom-workflow-data",
port: 5173,
// baseUrl overrides port if set
baseUrl: "https://local.example.com:3000",
recoverActiveRuns: true, // overrides WORKFLOW_LOCAL_RECOVER_ACTIVE_RUNS
streamFlushIntervalMs: 10, // WORKFLOW_STREAM_FLUSH_INTERVAL_MS, if set, overrides this
});
```
```bash title=".env"
WORKFLOW_TARGET_WORLD="./my-world.ts"
```
`createWorld()` also accepts `tag`, which scopes local storage files to a suffix. It is mainly used by test harnesses that share one `.workflow-data` directory.
## Data directory layout
Each run's event and step files are stored in their own directory (`events/<runId>/`, `steps/<runId>/`). A directory that mixes both layouts, or holds `.json` files in `events/` or `steps/` that the World did not write, is never deleted: starting fails with a `DataDirLayoutError` that lists the files.
## Limitations
The Local World is designed for development, not production:
- **In-memory queue**: Workflow messages, including queued step invocations, do not persist across server restarts.
- **Filesystem storage**: Data is stored in local JSON files.
- **Single instance**: The Local World cannot handle distributed deployments.
- **No authentication**: The Local World is suitable only for local development.
For production deployments, use the [Vercel World](/worlds/vercel), which handles execution, persistence, multi-tenancy, scale, observability, and security for you on Vercel, or check out the [Postgres World](/worlds/postgres) - a tested reference implementation that implements the complete World spec and can be used to deploy workflows anywhere.