# Manage deferred runs

Deferred submission creates a durable run and returns before extraction finishes. Use it when work must survive process restarts or exceed an inbound request deadline.

## Submit, wait, and retrieve

```python
from makra import Makra, run_succeeded

with Makra() as client:
    handle = client.submit_extract(
        ["https://shop.example/products/atlas-lamp"],
        {"price": "The current selling price"},
        idempotency_key="catalog-atlas-lamp-2026-08-21",
    )

    run = handle.wait(timeout=900)
    if not run_succeeded(run):
        raise RuntimeError(f"Run ended in {run.get('state')!r}")

    result = handle.result()
    print(result)
```

`RunHandle` keeps the run ID and delegates `refresh()`, `wait()`, `stream()`, `result()`, and `cancel()` to its client. Keep the client open while using the handle.

## Polling behavior

`wait_for_run()` respects the server's `poll_after_ms` suggestion and never polls faster than your `poll_interval`. By default it raises `MakraRunFailedError` for failed, cancelled, and budget-exhausted states.

Set `raise_on_failure=False` when a coordinator needs the terminal metadata for every outcome.

```python
from makra import Makra

with Makra() as client:
    run = client.wait_for_run(
        "your-run-id",
        timeout=900,
        poll_interval=5,
        raise_on_failure=False,
    )
    print(run.get("state"), run.get("terminal_reason"))
```

## List and reconcile runs

`list_runs()` returns non-archived runs newest first. Use `limit`, `cursor`, `feature`, and `state` filters. Limits must be between 1 and 100.

```python
from makra import Features, Makra, RunStates

with Makra() as client:
    page = client.list_runs(
        limit=50,
        feature=Features.EXTRACT,
        state=RunStates.RUNNING,
    )
    for run in page.get("items", []):
        print(run.get("id"), run.get("state"))
```

Use the returned `next_cursor` for the next page. Do not derive a cursor from IDs or timestamps.

## Cancel carefully

Cancellation is a request, not proof that work stopped at that instant. A run can enter `cancel_requested` before reaching `cancelled`, and a race may allow normal completion first. Calling `cancel()` more than once is safe.

Always reconcile to a terminal state before releasing your own job record.

Next, read [Reliability and idempotency](/markdown/makra-sdk/v0.0.4-beta/production/reliability-and-idempotency).
