Workers IO workers.io
skills docs blog login

First Simulation

Define one user-critical workflow, run it with faults, and inspect the result.


This guide takes one workflow your users depend on and runs it as a simulation. By the end, you will have a workload file, an optional external mock, a network fault model, and one run you can inspect from the web UI or the wio CLI.

Choose a workflow that matters but is small enough to run from one command: create an account, submit a payment, process a queued job, sync data, renew a lease, or recover after a failed API call.

1. Install and sign in

Install the CLI:

npm install -g @workersio/cli

Sign in:

wio auth login

Then confirm you can see your projects:

wio projects ls

2. Pick a prepared project

Your project must be connected and prepared before you run a simulation.

wio projects get <project-id>

If the project is not prepared, request a prepare:

wio projects prepare <project-id>

In the web UI, open app.workers.io, choose the project, and wait until it is prepared before continuing.

3. Add a workload

A workload is the command that drives the behavior you care about and checks whether it stayed correct.

Create a file in your repo, for example:

.workers/workloads/checkout.py

Use your real app entrypoints and checks. This example shows the shape:

import json
import os
import sys
import urllib.request

BASE_URL = os.environ["APP_URL"]


def post(path, body):
    data = json.dumps(body).encode("utf-8")
    req = urllib.request.Request(
        f"{BASE_URL}{path}",
        data=data,
        headers={"content-type": "application/json"},
        method="POST",
    )
    with urllib.request.urlopen(req, timeout=10) as res:
        return json.loads(res.read())


order = post("/checkout", {"user_id": "u_123", "sku": "starter"})

if order.get("status") != "paid":
    print(f"INVARIANT FAIL checkout_paid status={order.get('status')}")
    sys.exit(1)

print(f"INVARIANT PASS checkout_paid order_id={order.get('id')}")

The important parts are:

  • Drive a real workflow.
  • Check an invariant your users care about.
  • Exit non-zero when the invariant fails.
  • Print enough context to debug the failure later.

If your workflow needs a local service, make the command start that service before running the workload, or set APP_URL to the test endpoint you want to exercise.

4. Mock external services

If the workload calls an external service, add an external mock file:

.workers/external-mocks.json

Example:

{
  "data": {
    "pairs": [
      {
        "request": {
          "method": [{ "matcher": "exact", "value": "POST" }],
          "destination": [
            { "matcher": "exact", "value": "payments.example.com" }
          ],
          "path": [{ "matcher": "exact", "value": "/charge" }]
        },
        "response": {
          "status": 200,
          "body": "{\"id\":\"pay_123\",\"status\":\"succeeded\"}",
          "encodedBody": false,
          "headers": {
            "Content-Type": ["application/json"]
          }
        }
      }
    ]
  },
  "meta": {
    "schemaVersion": "v5.2"
  }
}

Use mocks for service behavior: success responses, retryable failures, permanent failures, unusual payloads, and state transitions.

5. Add a network fault

Network fault models live in your repo. For the CLI, put named network faults under:

.workers/fault/net/

Create:

.workers/fault/net/slow-network.json

Example:

{
  "version": 1,
  "lo": {
    "default": {
      "delay": {
        "time_ms": 250,
        "jitter_ms": 50
      },
      "loss": {
        "kind": "random",
        "percent": 1
      }
    }
  }
}

Use fault models for transport behavior: latency, jitter, packet loss, packet corruption, duplication, reordering, rate limits, and blocked paths.

6. Run from the CLI

Start with a baseline run. Baseline means no network fault:

wio simulate create <project-id> \
  --command "python3 .workers/workloads/checkout.py" \
  --workload-path ".workers/workloads/checkout.py" \
  --depth 1

Then run the same workload with the network fault across more seeds:

wio simulate create <project-id> \
  --command "python3 .workers/workloads/checkout.py" \
  --workload-path ".workers/workloads/checkout.py" \
  --faults slow-network \
  --depth 20 \
  --timeout 300 \
  --mem 1024

--depth is the number of seeds per fault model. With one fault and --depth 20, Workers IO creates 20 runs. With two faults and --depth 20, it creates 40 runs.

7. Run from the web UI

Open app.workers.io, go to Workloads, and click New Workload.

Choose:

  • Project: your prepared project.
  • Workload file: .workers/workloads/checkout.py.
  • Fault Models: slow-network.
  • Command: python3 .workers/workloads/checkout.py.
  • Depth: 20.
  • Timeout: 300.
  • Memory: 1024.

Click Start.

8. Watch progress

List simulation batches:

wio simulate ls

Check one batch:

wio simulate status <exploration-id>

List failed runs:

wio workloads ls --state failed

In the web UI, open the run to see Logs, Workload, Fault, External Mocks, Details, and Artifacts.

9. Inspect and rerun

Inspect a failed run:

wio workloads get <run-id>
wio workloads logs <run-id>

List artifacts:

wio artifacts ls <run-id>

Download an artifact:

wio artifacts download <run-id> stdout.log

Rerun a completed run with the same details:

wio workloads rerun <run-id>

Rerun uses the same command, seed, fault model, memory, timeout, branch, workload file, and mock configuration. For failed runs, inspect the logs, captured files, and artifacts, then sync the fix and rerun the same workload before increasing depth.

Next

Read Workloads to design stronger workloads, then read CLI for the full command reference.