Skip to content

Named child runs that survive migration and resurrection #1127

Description

@vdusek

When an Actor migrates or is resurrected, the process restarts and every in-flight Actor.call is
lost. Nothing records which child runs were already started, so the restarted Actor starts them all
over again, paying twice and duplicating the work. A user cannot fix this from the outside, because
only the SDK sees the migration.

Proposal

An optional name on Actor.start / Actor.call:

run = await Actor.start('apify/web-scraper', run_input, name='scrape-eu')

With a name, the SDK keeps a name → run ID map in the key-value store and reattaches to the
recorded run after a restart. A new run is started only when nothing is recorded under that name, or
the recorded one ended in a state that cannot be resumed.

Actor.use_state (src/apify/_actor.py:1429) already provides a KVS-backed dict that survives
migration, so the registry can be built on it.

Prior art

apify-orchestrator, which splits this into a tracker and a find-or-start step:

✍️ Drafted by Claude Code

Activity

  1. added
    t-toolingIssues with this label are in the ownership of the tooling team.
    on Sep 16, 2026
  2. B4nan commented on Sep 22, 2026

    @B4nan
    Member

    Three things worth pinning down in the design, from comparing the orchestrator and the skill in apify/agent-skills#90:

    • use_state persists on interval and on MIGRATING. A hard kill (OOM, timeout) between start returning and the next persist leaves an orphan child that gets started again after resurrection. The registry should write the name → run ID entry to the KVS synchronously after start returns, not wait for the periodic persist. The full fix is an idempotency key on the run-start endpoint scoped to the parent run, which I'll raise with the platform team separately.
    • Rejoin rule for a recorded run: READY/RUNNING → attach, SUCCEEDED → return as is, ABORTED/TIMED-OUT → resurrect it (Actors are expected to be resumable, and it's cheaper than starting over), FAILED → start a new run under the same name and keep the old one in history. The orchestrator restarts in all the non-OK cases; the skill asks for resurrection. I'd go with resurrect.
    • Names should be explicit. The orchestrator falls back to hashing (actor id, input, options) and then has to throw AmbiguousRunRequestError when the same unnamed call happens twice in one process. Requiring name avoids that class of surprise.
  3. self-assigned this
    on Sep 30, 2026
  4. added a commit that references this issue on Oct 9, 2026
    95dbc7c
  5. vdusek commented on Oct 9, 2026

    @vdusek
    ContributorAuthor

    resolved by #1149

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request.t-toolingIssues with this label are in the ownership of the tooling team.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions