Skip to content

Limits and rough edges

What an experimental environment cannot do, and what it does that will surprise you. Read this alongside getting-started.md.

By default you get 50 concurrent environments per person. Retiring one is adsk-experiment env archive, and that frees the slot straight away.

The API always reports environmentQuota and environmentsInUse in GET /v1/whoami. It only treats quota as “low” when environmentQuotaLow is true, which means less than 20% of slots remain or one slot is left.

Archiving reclaims the published content, the CI jobs, the component registrations and the hostnames, and archives the GitHub repository. It is asynchronous: the environment leaves adsk-experiment env list at once and sits in archiving under env list --all until the pipeline reports back, minutes rather than seconds. An archived environment is still renewable.

adsk-experiment env delete is a different command and isn’t built yet: it names the purge past archived that removes the record for good (roadmap F.2). It exits 9 with not_implemented and changes nothing. Don’t reach for it to tidy up — env archive is the tidy-up.

Free up a slot without lifting a finger: set a short TTL (time to live) on anything throwaway (--ttl 1d); expiry archives the same way.

Environments expire after 14 days by default. Renewing resets the clock from now, not from the original expiry, up to the absoluteDeadline on the record, which caps how far any renewal can push it out.

An expired environment’s repository turns read-only and revokes your push access. Renewing restores both. If pushes on an old experiment suddenly start failing: check expiry before you assume it’s broken.

Archiving an environment doesn’t delete your code. Its repository is archived: branches and history survive, but become read-only. Before you archive: commit or push anything you still need. Only the platform team can restore write access afterward.

There’s no backend runtime (roadmap H.1). “Dynamic” here means client-side only: routing, search, state kept in localStorage. If your prototype needs a server, this isn’t the right tool yet.

Client-side routing has to be hash-based (#/page) unless someone has configured a 404-to-index rule at the edge. Path routing looks fine locally and 404s on a deep link in production. Test a deep link against the published hostname before you choose path routing; a local dev server will not reproduce the 404.

The publish path scans your build output for PII (personally identifiable information) and fails the build on a hit. That covers real email addresses, IPv4 addresses, and long digit strings that read as phone numbers (AWS account IDs do).

This isn’t configurable, and there’s no way around the gate. Fix a hit: redact the content and rebuild. Measured 2026-08-25: a fixture built from this repository’s own ADRs failed with reason:pii_scan_failed on teammate addresses and infrastructure addresses in five documents.

Catch it before you push: run this against your built output. It’s faster than waiting for a red build two minutes later:

Terminal window
grep -rhoE '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}|\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b|\b[0-9]{10,}\b' \
<your output directory> | sort -u

People get this wrong in both directions.

  • The repository is public within Autodesk. Anyone with a GHES (GitHub Enterprise Server) account can browse and clone it. Sharing org/name with a colleague is enough for them to read your source. Public here means visible to Autodesk, not to the internet.
  • Only you can push. You can’t add anyone else. Your grant is push, not admin, so you can’t manage collaborators yourself. A teammate who needs to commit has to be added by the platform team, one repository at a time. adsk-experiment env collaborators set isn’t that command, despite the name. That list only controls who’s emailed before the environment expires. It grants no access.

Every hostname sits behind Autodesk SSO. A Lambda@Edge function authenticates the viewer before anything else runs, so an anonymous request gets a 302 redirect to login.microsoftonline.com on every path, including /robots.txt. Measured on every live hostname on 2026-08-25.

This is stronger protection than these docs used to claim, but the work is still marked partial (roadmap B.3): the Trust security review and the latency benchmark are open as CLOUDOSAI-1496. Put nothing confidential in an experiment, and no credentials in its repository. If something looks wrong: the edge isn’t observable from outside. x-cache always reports LambdaGeneratedResponse, never a hit or a miss, because the auth check runs before the cache. And a URL that fails in your regular browser but works in incognito is a stale cookie for that domain, not a broken deploy.

Phase timings from the first run measured this way, on sb:

PhaseTook
create39s
register14s
merge the pull request7m 10s
build2m 43s
deploy2m 07s

The pull request’s security scans dominate the timing. Nobody expects that going in, because nothing else about this product mentions it. Both pipelines are shared, so a two-minute build and a nine-minute build can be the same code an hour apart, depending on queue depth on the CloudBees controller. One run is not a benchmark.

Two failures are worth exactly one retry:

  • job_missing on the first build of a newly registered component. The message reads as terminal, but for a component registered moments ago it’s usually wrong: the multibranch project hasn’t finished scanning its default branch yet. Wait 60 seconds and trigger again. A second identical failure is the real thing.
  • not_found_or_not_owned on a component that’s fine. There’s a sandbox stack at https://api-sb.experiment.autodesk.com alongside dv, each with its own build server. A component created against one is invisible to the other. adsk-experiment doctor shows which one you’re pointed at. The default is dv.

Every failure carries a named error code. The full list, the exit code each maps to, and what each commits us to, is architecture/failure-contract.md.

ErrorMeaningRetry?
unauthenticatedNot signed in: run adsk-experiment loginAfter login
quota_exceededAt your limit of environments (default: 50, unless your stack override differs)Never
not_implementedThe command exists and the thing behind it is not builtNo
provisioning_failedCreated, and provisioning did not finishNever: archive it, then create again

adsk-experiment has no deploy or logs command: publishing goes through the CBCI and Harness pipelines, driven by an agent through their MCP servers, not through the CLI (ADR-0009). The two names were registered as permanent not_implemented stubs until ADR-0055 removed them outright.

Every command takes --output json, including on failure, so an agent never has to parse prose at the moment something breaks. Branch on error.code or the exit code, never on message.