Skip to content

Add multi-region sandbox support - #308

Open
scotttrinh wants to merge 3 commits into
mainfrom
sandbox-multi-region
Open

Add multi-region sandbox support#308
scotttrinh wants to merge 3 commits into
mainfrom
sandbox-multi-region

Conversation

@scotttrinh

@scotttrinh scotttrinh commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

This ports the multi-region sandbox support from vercel/sandbox#301 across create, fork, get-or-create, update, and snapshot metadata.

The Python API intentionally differs a little from the TypeScript SDK: instead of separate region and failoverRegions values, it accepts one ordered regions iterable. The first region is preferred and the rest are failovers, which keeps the placement preference together and maps back to the backend fields internally.

Edit: I went back on this due to how the actual backend treats region and failoverRegions. Failovers are not ordered by list-order, they are ordered by proximity to the primary region. This changes what I had originally understood, so we're going with two separate properties.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds multi-region sandbox support to the vercel-sandbox Python SDK by introducing an ordered regions input (preferred region first, remaining as failovers) and mapping that to the backend’s region + failoverRegions fields across create, fork, get-or-create, update, and snapshot metadata.

Changes:

  • Add regions as an ordered public input for sandbox create/fork/get-or-create/update flows, normalized internally.
  • Extend API request/response modeling to encode/decode region + failoverRegions, and expose snapshot region availability as a tuple.
  • Update tests, an example, and add a news fragment documenting the new capability.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/vercel-sandbox/vercel/sandbox/sync.py Exposes regions on sync convenience functions and forwards through to internal runtime.
src/vercel-sandbox/vercel/sandbox/_internal/sync_runtime.py Wires regions through sync runtime operations and normalizes inputs before service/API calls.
src/vercel-sandbox/vercel/sandbox/_internal/state.py Replaces single region state with ordered regions for sandboxes and snapshots.
src/vercel-sandbox/vercel/sandbox/_internal/service.py Adds regions plumbing on service methods so API client can encode region/failovers.
src/vercel-sandbox/vercel/sandbox/_internal/runtime_common.py Updates public handle accessors to expose regions on sandbox and snapshot handles.
src/vercel-sandbox/vercel/sandbox/_internal/models.py Introduces RegionsInput and normalize_regions() validation/normalization helper.
src/vercel-sandbox/vercel/sandbox/_internal/async_runtime.py Adds regions to async operations/updates and passes normalized tuples into service/API layers.
src/vercel-sandbox/vercel/sandbox/_internal/api_client.py Implements request encoding (region/failoverRegions) and response decoding into ordered regions.
src/vercel-sandbox/vercel/sandbox/init.py Adds regions to the public async surface functions and re-exports the input type for typing.
src/vercel-sandbox/tests/test_sandbox_public_flow.py Updates mocks/assertions to validate request encoding and handle properties for multi-region.
src/vercel-sandbox/examples/sandbox_03_snapshot_restore.py Demonstrates creating a sandbox with multiple regions and printing snapshot region availability.
changes/vercel-sandbox/multi-region.feature.md Adds a changelog/news fragment for the new regions configuration feature.
Suppressed comments (1)

src/vercel-sandbox/vercel/sandbox/_internal/runtime_common.py:463

  • This change removes the Sandbox.region accessor in favor of Sandbox.regions, which is a breaking API change for consumers. Consider keeping region as a compatibility alias that returns the preferred region (regions[0]).
    @property
    def regions(self) -> tuple[str, ...]:
        return self._payload.regions

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/vercel-sandbox/vercel/sandbox/_internal/models.py Outdated
Comment thread src/vercel-sandbox/vercel/sandbox/_internal/runtime_common.py
Comment thread src/vercel-sandbox/vercel/sandbox/_internal/models.py Outdated
Expose ordered region preferences for sandbox creation, forks,
and updates while keeping backend field mapping internal.

Report sandbox and snapshot availability as immutable region
tuples while sessions retain their actual landing region.
I was wrong in my assumption that failover_regions was an ordered
preference. Failover actually works by selecting the next closest
region, so instead of having to explain that explicitly, let's just do
the obvious thing here.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/vercel-sandbox/vercel/sandbox/_internal/models.py:34

  • normalize_failover_regions will treat a single string like "sfo1" as an iterable of characters ("s", "f", "o", "1"), which will pass the current validation and produce an invalid failoverRegions payload. This should explicitly reject str/bytes inputs so accidental misuse fails fast with a clear error.
    if regions is None:
        return None
    normalized = tuple(regions)
    if any(not isinstance(region, str) or not region for region in normalized):
        raise ValueError("failover_regions must contain non-empty strings")

@scotttrinh
scotttrinh marked this pull request as ready for review August 20, 2026 01:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants