Skip to content

Some improvements to actor snapshots #773

Description

There are a few things about snapshots which I would like to revisit before we commit to it.

Terminology and concepts

When we suspend, we generate a snapshot ID, which encodes the timestamp at which the snapshot is created plus a random suffix. They look like this: 2026-08-05T16:47:28-04:00-N7GBFQ2XKJ4ZLWMR6TYHPVCD3A.

When the snapshot is uploaded to GCS, we construct a snapshot URL, which consist of the base path on the ActorTemplate and the snapshot ID. It looks like this:

gs://my-bucket/snapshots/secret-agent/snapshots/2026-08-05T16:47:28-04:00-N7GBFQ2XKJ4ZLWMR6TYHPVCD3A

Note that the ID goes into that URI raw — those colons end up verbatim in the GCS object names. The sanitizing happens somewhere else entirely: after the upload, when we finalize the suspend, we parse the ID back out of the URI and rewrite it (:-, +-, plus lowercasing) to get a valid Substrate resource name, because ObjectRef.name is validated as a DNS-1123 label.

So one snapshot ends up with two IDs:

in GCS 2026-08-05T16:47:28-04:00-N7GBFQ2XKJ4ZLWMR6TYHPVCD3A
in the API (ActorSnapshot.metadata.name) 2026-08-05t16-47-28-04-00-n7gbfq2xkj4zlwmr6typvcd3a

Note that the rewrite is one-way: : and + both become -, so you can't get from the API name back to the path (t16-47-28-04-00 — was that -04:00 or +04:00?).

I think we need to simplify the concepts and use consistent terminology throughout the codebase.

  • There is no snapshot ID. When we create a new snapshot, we allocate a new snapshot name, which is used for both the final snapshot URI and the ActorSnapshot name.

  • We don't encode semantic information into the name. Today we try to encode a timestamp, but it's not really needed. The ActorSnapshot resource has a create_time timestamp already.

  • We have three concepts:

    • Snapshot location: This is the base path which is dictated by ActorTemplate.spec.snapshotsConfig.Location.
    • Snapshot name: The identifier of the snapshot. A single UUID. Opaque.
    • Snapshot URI: The address of a given snapshot. This is <location>/snapshots/<atespace>/<snapshot-name>.

This removes the confusion about snapshot name, snapshot id (sanitized vs not sanitized), etc.

ActorSnapshot has an internal version in storage

The ActorSnapshot representation in ValKey today is a json wrapper of the proto, which includes the (not sanitized!) snapshot ID.
We should just add a snapshot_uri to the ActorSnapshot proto.

Bookkeeping during operations

Today the suspend and pause workflows are reusing the in_progress_snapshot field in the Actor proto for storing two different concepts. We should split them.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions