What are the @local, @prerelease and @release views on an Azure Artifacts feed, and what changes when you promote a package version to a view?
answer
- filtered windows onto one feed
- local is everything, others start empty
- promotion moves a label, not bytes
- view name goes in the URL
- promoted versions escape retention
basics
~20 sViews are filtered, read-only slices of one Azure Artifacts feed. @local shows everything the feed holds; @prerelease and @release show only versions you promote into them. Promotion copies no bytes — it just makes a version visible at the view's URL.
solid answer
~50 sEvery Azure Artifacts feed is created with three views: `@local`, `@prerelease` and `@release`. `@local` is the whole feed — everything published to it plus everything saved from upstream sources. The other two start empty and gain content only when you **promote** a specific package version into them. Consumers choose a view by putting it in the endpoint URL, for example `.../_packaging/MyFeed@release/nuget/v3/index.json`, so a team that only wants blessed builds subscribes to `@release` and never sees the noise in `@local`. Promotion is a metadata operation: no bytes are copied, there is no second feed, and the version keeps its identity. Two side effects matter in practice — a version promoted to any view is exempt from the feed's retention-policy deletions, and consuming a feed from another organization as an upstream is done through one of its views rather than the raw feed.
code
bash · 9 lines# Restore only blessed versions: point the client at the @release view
dotnet nuget add source \
"https://pkgs.dev.azure.com/contoso/tools/_packaging/shared@release/nuget/v3/index.json" \
--name shared-release
# The same feed without a view suffix resolves to @local: everything, including prereleases
dotnet nuget add source \
"https://pkgs.dev.azure.com/contoso/tools/_packaging/shared/nuget/v3/index.json" \
--name shared-localgo deeper
Know that a feed has three views, that @local is everything, and that a consumer picks a view by appending @release to the feed name in the URL.
Explain that promotion is a metadata operation with no copy or rebuild, that the default views are conventions rather than automatic filters, and how a consumer's URL determines what they can resolve.
Show the operational angles: promotion as a gated pipeline step, retention exemption as the reason to promote anything you must keep, and the cross-organization upstream that requires a view.
Own the boundary decision — curated views inside one feed versus a separate consumer feed fed by an upstream — and be ready to defend how many promotion tiers a delivery flow can actually sustain.
## The shape of the thing A feed holds every version anyone ever published to it, plus every version saved from an upstream source. That is exactly what a build needs and exactly what a consumer does not: `1.4.0-alpha7` sitting next to `1.4.0` is a trap for anyone resolving a floating version range. A **view** is a filtered, read-only window onto that one feed. Three exist by default: - **`@local`** — everything the feed contains. This is the default view: a feed URL with no `@view` suffix resolves to it. - **`@prerelease`** — empty at creation; holds versions you promote as candidates. - **`@release`** — empty at creation; holds versions you promote as blessed. The names are conventions, not behaviour. Nothing in Azure Artifacts inspects a SemVer prerelease tag and files the package automatically — promotion is an explicit action taken by a person or a pipeline step. ## What promotion actually does Promoting `MyLib 2.3.1` to `@release` does **not** copy the package, create a second storage location, or change the version string. It records that this version is a member of that view. The bits stay exactly where they were; the digest is unchanged; the package identity a consumer resolves is identical. That property is the whole point. The artifact a consumer pulls from `@release` is byte-for-byte the artifact that was tested when it sat in `@local` — you moved a label, not a build. ## How a consumer selects a view The view goes in the URL, suffixed to the feed name with `@`: ```text https://pkgs.dev.azure.com/{org}/{project}/_packaging/{feed}@release/nuget/v3/index.json ``` A feed URL without `@view` behaves as `@local`. So the typical arrangement is: CI pipelines publish into the feed and read from `@local` (they need everything, including their own just-built prerelease); downstream teams point their `nuget.config` or `.npmrc` at `@release` and are structurally unable to pick up an untested version, because the view simply does not list it. This is a cleaner control than naming conventions. Telling teams "don't reference anything with `-alpha` in the version" relies on discipline; giving them a URL that cannot return those versions does not. ## Two consequences people miss **Retention exemption.** A feed's retention policy prunes older versions per package. Versions promoted to a view are excluded from that pruning. This is not incidental — it is the intended way to keep a version that some long-lived release still depends on. A team that never promotes anything and then discovers retention deleted a version an old release pins has found this rule the hard way. **Cross-organization upstreams.** When you want feed B in another Azure DevOps organization to consume feed A, the upstream is configured against one of A's views, not against A itself. So a shop that shares packages across organizations must actually operate views, whether or not it wanted a promotion workflow. ## Fitting it into a pipeline The common pattern is: 1. CI builds and publishes `2.3.1-ci.42` to the feed on every merge. It lands in `@local` only. 2. A quality stage — integration tests, a soak, a manual sign-off — runs against that exact version. 3. On success a step promotes that version to `@prerelease` for early adopters, and later to `@release` once it has been in use. Promotion can be done from the Artifacts UI, through the REST API, or by a pipeline task, so it can be gated by an approval like any other deployment step. Nothing rebuilds at any point, which is why the promoted version's provenance still refers to the original build. ## Limits to be honest about Views are per-feed, so they are not a substitute for separating trust domains — anyone with Reader on the feed can read `@local` directly if they know the URL. Views filter, they do not enforce isolation. If you need a hard boundary (contractors who must only ever see released packages), a second feed consuming the first as an upstream through its `@release` view is the stronger arrangement. And because views are additive labels, an accidentally promoted bad version has to be explicitly removed from the view; nothing expires it for you.
- Does promoting a package to @release create a second copy of the artifact?No. Promotion records view membership against the existing version; the stored bytes and the package identity are untouched. That is what makes it a safe promotion step — the consumer of `@release` gets exactly the artifact that was tested, with no rebuild and no chance of a differing binary.
- How would you stop a downstream team from accidentally consuming a nightly prerelease build?Give them the `@release` view URL rather than the bare feed URL, and promote only versions that have passed the quality gate. The view cannot list unpromoted versions, so even a floating version range or a `--prerelease` flag has nothing untested to resolve to.
- Are the three default views automatic — does a version with a SemVer prerelease tag land in @prerelease by itself?No. The names are conventions only; Azure Artifacts never inspects the version string to file a package. Every version starts in `@local` and reaches another view solely through an explicit promotion, done from the UI, the REST API, or a pipeline step you wire into your release flow.
- If views only filter, when do you need a second feed instead?When you need isolation rather than curation. Anyone with Reader on the feed can query `@local` directly, so views do not hide anything from an authorized consumer. For an audience that must never see unreleased packages, create a separate feed whose upstream is the first feed's `@release` view, and grant them access only to that.
saying these in an interview costs you the question
- Thinking promotion copies the package into a second feed
- Assuming prerelease versions are sorted into @prerelease automatically
- Believing a view hides packages from anyone with feed Reader access
- Forgetting that promoted versions are exempt from retention
- Treating the view name as a version suffix rather than part of the URL