Azure Artifacts: The Complete Guide
A friendly, in-depth tour of Microsoft's package management service inside Azure DevOps. Learn how teams store, share, version, and protect the building blocks of their software, and how to keep builds fast, repeatable, and safe from supply chain surprises.
Imagine a workshop where a hundred carpenters build furniture. Almost nobody makes their own screws, hinges, or glass. They buy ready-made parts, and they also make special parts of their own, such as a custom drawer slider that every table needs. Now imagine the parts are scattered across drawers, other people’s garages, and old emails. A carpenter cannot find the right slider, uses the wrong size, and a table collapses. What the workshop needs is one well-organized, locked, labeled parts warehouse, where every part has a version number, nothing is ever swapped silently, and the warehouse keeps spare copies of popular outside parts in case the supplier closes.
Software teams have exactly this problem. Modern applications are built from hundreds of reusable pieces called packages. Azure Artifacts is the parts warehouse. In this guide you will learn what it is, how its pieces fit together, how a package travels from a developer to a build server and into an application, how it protects you from tampered or vanished packages, and how to run it well in a real company. Every new term is explained when it first appears, and every big idea comes with an everyday comparison.
1What Is Azure Artifacts?
A managed service for hosting, sharing, and controlling the reusable pieces of software that your teams create and consume.
Starting with the word “package”
Developers do not write everything from scratch. If you need to read a spreadsheet, send an email, or draw a chart, you use code that someone else wrote and shared. That shared code is bundled into a package: a single file, usually compressed, containing the code, a name, a version number, and a list of other packages it needs. Each programming world has its own package format and its own tool to fetch them. .NET developers use NuGet packages, JavaScript developers use npm packages, Java developers use Maven packages, and Python developers use PyPI-style packages.
The tool that downloads and installs these packages is called a package manager. It reads your project’s list of needed packages, fetches each from a registry (a website that stores packages), and puts them where the build can find them. The famous public registries are open to the world and hold millions of packages.
The company problem
Public registries are wonderful, but companies have needs they do not meet.
- Private code: You have shared libraries that must not be public, such as your logging helper or your payment client.
- Reliability: If the public registry is down, or a package is deleted by its author, your builds break.
- Safety: A malicious package with a name similar to yours could sneak into your product.
- Control: You want to know who published what, who can use it, and which versions are approved.
What Azure Artifacts does
Azure Artifacts is a package management service that is part of Azure DevOps, Microsoft’s set of tools for planning, building, testing, and releasing software. It lets your organization create private registries called feeds, publish your own packages to them, and download packages from them. It can also act as a middleman for public registries, saving a copy of each public package you use. It supports several package types with their native tools, so developers keep using the commands they already know.
Think of a company library with a head librarian. Staff borrow books from the shelves (feeds). The librarian also orders books from outside bookshops when someone asks, and keeps a copy on the shelf for next time (upstream caching). Every book has an edition number, and the librarian never rewrites a printed edition. If a mistake is found, a new edition is issued.
Publish your own
Package shared code once, and let every team reuse it instead of copying and pasting.
One source for dependencies
Builds fetch everything from one trusted address, whether the package is yours or from the public.
Control and cache
Saved copies of public packages keep builds working and let you control which versions get in.
Know what is where
See who published a version, when, and which pipeline produced it.
Azure Artifacts stores packages that code depends on. It is not where you store your source code, and it is not a place for container images. Chapter 2 sorts out these differences.
2Azure Artifacts and Its Neighbors
The word “artifact” is used for several different things in the Microsoft world. Sorting them out now saves a lot of confusion.
flowchart LR
DEV["Developers write code"] --> REPO["Source repository"]
REPO --> PIPE["Build pipeline"]
PIPE --> PKG["Packages published to Azure Artifacts feed"]
PIPE --> PA["Pipeline artifacts: temporary build outputs"]
PIPE --> IMG["Container images to Azure Container Registry"]
PKG --> OTHER["Other projects consume the packages"]
PUB["Public registries"] --> PKG
| Thing | What it is | Where it lives | Lifetime |
|---|---|---|---|
| Azure Artifacts package | A versioned, reusable library shared across projects | An Azure Artifacts feed | Long-lived, managed by retention policy |
| Pipeline artifact | Files produced by one pipeline run, handed to later stages or downloads | Attached to the pipeline run | Short, tied to run retention |
| Container image | A packaged application with its environment | A container registry such as Azure Container Registry | Long-lived, own policies |
| Source code | The text files developers write | A repository, such as Azure Repos or GitHub | Permanent history |
Comparing with other package hosts
Public registries
Open and huge, but outside your control. Anyone can publish, and packages can change or disappear.
GitHub Packages
Package hosting tied to GitHub repositories and permissions. A natural fit when your code lives in GitHub.
Third-party repository managers
Products such as Artifactory and Nexus offer many formats and advanced features, often self-hosted or sold as services.
Azure Container Registry
The place for container images, with its own scanning and geo-replication features.
Choosing between them
If your teams already use Azure DevOps for pipelines and permissions, Azure Artifacts is the smoothest choice, because identities, projects, and pipelines are already connected. If your code and pipelines live in GitHub, GitHub Packages fits better. If you need unusual package formats or very advanced policy features, a dedicated repository manager may be worth considering. Many large companies use more than one and connect them.
A pipeline artifact is the leftover sawdust and offcuts from today’s job, kept briefly and swept away. An Azure Artifacts package is a finished, labeled part that goes into the warehouse for other carpenters to use for years. A container image is a fully assembled piece of furniture, shipped in its own crate.
Supported package types, limits, and pricing are updated over time. Use this guide to understand the shape of the service, then confirm exact capabilities on Microsoft’s official pages before you decide.
3Core Concepts You Must Know
A handful of words appear in every Azure Artifacts conversation. Learn them once and the rest becomes easy.
Organization and project
In Azure DevOps, an organization is the top-level account of your company. Inside it live projects, each holding the work of a team: code, pipelines, boards, and packages. Both matter for Artifacts, since a feed can belong to either.
Feed
A feed is a private registry: a named container that holds packages and controls who may read or publish them. You can have many feeds, for example one per team, one per product, or one shared by the whole company. Developers point their package manager at the feed’s address.
Package and version
A package is the reusable unit, identified by name. A version is one specific release of it. Versions usually follow semantic versioning, written as three numbers separated by dots, such as 2.4.1. The first number (major) changes when something breaks compatibility, the second (minor) when new features are added safely, and the third (patch) for small fixes. A suffix such as “beta” marks a pre-release, a version not yet considered final.
Immutability
Once a version is published, it can never be changed. You cannot overwrite version 2.4.1 with different contents. This immutability guarantees that every build that asked for 2.4.1 got identical bits, today or next year. To fix a mistake, you publish a new version.
Upstream source
An upstream source is another registry that a feed can pull from, such as a public registry or another feed. When someone asks the feed for a package it does not hold, it fetches it from upstream and keeps a copy.
View
A view is a filtered window onto a feed, showing only versions that have been promoted into it, for example “pre-release” or “release”. Consumers who want only approved versions point at a view instead of the whole feed.
Retention policy
A retention policy is an automatic cleanup rule, such as “keep at most the latest fifty versions of each package”, to control storage use.
Permissions
Access is given through roles on a feed. A reader can download, a collaborator can also save packages from upstream, a contributor can publish, and an owner can manage settings and permissions.
flowchart TD
ORG["Azure DevOps organization"] --> PRJ["Project"]
ORG --> OF["Organization scoped feed"]
PRJ --> PF["Project scoped feed"]
PF --> PK["Package"]
PK --> V1["Version 1.0.0"]
PK --> V2["Version 1.1.0"]
PK --> V3["Version 1.2.0-beta"]
PF --> VW["Views: prerelease and release"]
PF --> UP["Upstream sources"]
PF --> RP["Retention policy"]
The organization is the whole company building. A feed is one warehouse room. A package is a type of part, such as “drawer slider”. A version is the numbered model of that part. A view is the “approved parts” shelf at the front. Upstream is the outside supplier that the warehouse orders from.
A feed is not a package and not a project. It is the registry that holds packages. Projects can have many feeds, and one feed can serve many projects if it is scoped to the organization.
4Package Types and Protocols
Azure Artifacts speaks the native language of several ecosystems, so developers use the tools they already know.
NuGet
Libraries for C# and other .NET languages. Used with the dotnet and NuGet command tools and the major .NET editors.
npm
Packages for web and server JavaScript. Works with the npm tool and compatible clients.
Maven and Gradle
Java libraries and build plugins, for projects built with Maven or Gradle.
Python packages
Libraries installed with pip and published with standard Python publishing tools.
Cargo
Crates for Rust projects, using the standard Rust package tool.
Universal Packages
A Microsoft format for any collection of files: models, datasets, tools, installers, or large binaries, with its own command line.
Why native protocols matter
A protocol is the agreed way for a tool and a server to talk. Because Azure Artifacts implements each ecosystem’s protocol, a feed looks to the npm tool like any other npm registry, and to the NuGet tool like any other NuGet source. Developers change an address and a sign-in, not their habits. Build scripts keep working with tiny changes.
Universal Packages in detail
Not everything is a library. Teams also share large files: trained machine learning models, test data sets, installers, or tool kits. Universal Packages give such files a name, a version, and a home in a feed, with the same permissions and retention as other packages. They can be very large, and uploads and downloads are handled efficiently by breaking content into pieces and reusing pieces that already exist.
| Need | Best fit | Why |
|---|---|---|
| Shared .NET helper library | NuGet package | Native to the language and tools |
| Front-end component library | npm package | Standard in the JavaScript world |
| Shared Java service client | Maven package | Fits the Java build chain |
| Data science helpers | Python package | Installable with pip |
| Big model file or toolset | Universal Package | Versioned storage for any file collection |
| Application image to run | Container registry, not Artifacts | Different format and tooling |
One feed can hold several package types side by side. A full-stack team can keep its NuGet, npm, and Python packages in one feed, with one set of permissions.
5Feeds: Scope, Structure and Access
The feed is the central decision you make. Design it well and everything else becomes simpler.
Project-scoped and organization-scoped feeds
A feed can be project-scoped, belonging to a single project and inheriting its visibility, or organization-scoped, living at the top level and usable across all projects. Project-scoped feeds are the recommended default for new feeds in most cases, since they follow the project’s boundaries and are easier to reason about. Older feeds are often organization-scoped. Each style has its place.
Project-scoped
Owned by one team’s project. Permissions and visibility follow the project, which makes ownership clear.
Organization-scoped
Shared across projects. Good for company-wide libraries, but it needs more careful permission planning.
How many feeds?
There is no single right answer, but the options have clear trade-offs.
One shared feed
- Simple to find everything
- One set of upstream rules
- Easy for small companies
One shared feed, drawbacks
- Everyone sees everything
- Cleanup rules must suit all teams
- A mistake affects the whole company
Feed per team or product
- Clear ownership and permissions
- Separate retention and cleanup
- Smaller blast radius for mistakes
Feed per team, drawbacks
- Consumers must know many addresses
- Duplicate upstream copies use more storage
- More setup to maintain
A popular middle path: one feed for publicly sourced packages with upstreams enabled, which acts as the controlled gateway to the outside world, plus a separate feed per team for its own published packages. Teams then chain these using upstream sources.
flowchart TD
PUB["Public registries"] --> GW["Company gateway feed with public upstreams"]
GW --> TA["Team A feed"]
GW --> TB["Team B feed"]
TA --> BA["Team A builds"]
TB --> BB["Team B builds"]
TA -.->|"upstream"| TB
Visibility
A feed can be visible only to specific people and groups, to everyone in the organization, or, for feeds in public projects, to anyone on the internet. Pick the narrowest visibility that works, and remember that anything public cannot easily be taken back.
One big warehouse is easy to find things in but everyone has a key to everything. Many small rooms are safer but you need to know which door to knock on. The gateway feed is the receiving dock, where all outside deliveries are checked before being passed to individual rooms.
The scope of a feed, project or organization, is a design decision that is hard to reverse. Think before you create a feed, and write down who owns it.
6Architecture and Components
What sits behind a feed address, seen from a distance.
You never see the machines behind Azure Artifacts, because it is a cloud service run by Microsoft as part of Azure DevOps Services. Still, a rough picture explains its behavior. A request for a package enters through a protocol endpoint, passes an identity check and a permission check, is resolved against the feed’s metadata, and is served from durable storage, or fetched from an upstream source if needed.
flowchart TD
CL["Client tools: dotnet, npm, pip, Maven, Cargo, universal"] --> EP["Protocol endpoints per package type"]
EP --> AUTH["Identity and token validation"]
AUTH --> PERM["Feed permission check"]
PERM --> META["Feed metadata and package index"]
META --> STORE["Durable package storage"]
META --> UPS["Upstream proxy and cache"]
UPS --> EXT["Public registries and other feeds"]
EP -.-> AUD["Audit and usage records"]
Protocol endpoints
Each package type has an address that speaks that ecosystem’s protocol, so ordinary tools work unchanged.
Identity and permissions
The caller is identified by a token. The service checks that the identity holds a role on the feed that allows the requested action.
Metadata index
A catalog of package names, versions, dependencies, views, and status. Tools query this to decide what to download.
Package storage
Durable cloud storage that holds the package files themselves, replicated by the platform for safety.
Upstream proxy
When a requested package is not in the feed, this part asks the configured upstream, saves what it receives, and serves it.
Audit trail
Key actions, such as publishing, deleting, and changing permissions, are recorded for review.
A shared, multi-tenant service
Azure Artifacts serves many customers on shared infrastructure, with strict separation between organizations. Because the platform is shared, it applies usage limits and fair-use throttling, so one very busy client cannot slow down everyone else. A build that hammers the service with thousands of requests may see “too many requests” responses, and should be written to slow down and retry.
Cloud service and self-hosted server
Azure DevOps also comes as a product you can install in your own data center, called Azure DevOps Server. It includes package management too, with its own limits and feature set. This guide focuses on the cloud service, since that is what most teams use. If you must keep everything on your own servers, check the current feature list for the server version.
The endpoint is the loading bay with a label for each kind of delivery. The guard checks your badge, the clerk checks the catalog to find the shelf, the shelves hold the parts, and a courier fetches anything missing from the outside supplier, shelving a spare copy as it passes through.
7Internal Working: Versions, Resolution and Immutability
How a package manager decides which files to download, and why the answer is the same every time.
The dependency tree
Packages depend on other packages, which depend on others in turn, forming a dependency tree. Your application may list ten packages, but the full tree can contain hundreds. The package manager walks this tree, asks the feed for the list of available versions of each package, and picks versions that satisfy every rule. This is called dependency resolution.
Version ranges
A project rarely demands one exact version. It often says “any version from 2.4 up to, but not including, 3.0”. The package manager chooses the highest allowed version, or the lowest, depending on the ecosystem’s rules. Because a feed can publish new versions at any time, two builds run a week apart could pick different versions, unless you pin them. Many ecosystems offer a lock file, a record of the exact versions chosen, so that every build repeats the same choice.
A recipe that says “use any flour from this brand between type 1 and type 3” might give different cakes on different days. A recipe that says “use exactly this bag, batch number 4471” always gives the same cake. A lock file is the batch number.
Why immutability matters
Immutability protects three things. First, repeatability: version 2.4.1 means the same bits forever. Second, caching: tools and servers can safely keep copies of an immutable file without checking for changes. Third, trust: a security review of 2.4.1 stays valid, since nobody can swap its contents. Azure Artifacts enforces this: once a version has been published, publishing the same name and version again with different content is refused.
What you can do with a published version
Unlist or deprecate
Hide it from search and discourage new use, while existing builds can still fetch it.
Promote to a view
Mark it as approved by adding it to a view such as release.
Delete
Remove it. Deleted versions can be recovered from a recycle bin for a limited period, and the version number can never be reused for different content.
Fix forward
If a version is broken, publish a newer one. Do not try to replace the old one.
Metadata and the package index
Every package carries metadata: name, version, description, authors, dependencies, and license. The feed indexes this so that searches and resolution are fast without opening each file. For tools that need only to know “which versions exist?”, the index answers in a blink and the heavy file is downloaded only after the choice is made.
Storage efficiency
The service stores each package version once, however many feeds or views refer to it. Promoting a version into a view does not copy the file. It only adds a label. That is why promotion is instant and cheap, and why views are a good way to express approval without duplicating storage.
If asked why package versions are immutable, say: it makes builds repeatable, lets clients cache safely, and keeps security reviews valid, because version 2.4.1 always means the same bytes. Mistakes are fixed by publishing a newer version.
8Data Flow: Publish and Restore
Follow one package from the moment a developer creates it to the moment another team’s build uses it.
sequenceDiagram
participant D as Developer or pipeline
participant F as Azure Artifacts feed
participant S as Package storage
participant C as Consumer build
participant U as Public registry upstream
D->>F: Publish package version 1.2.0 with token
F->>F: Check identity, permission and version is new
F->>S: Store package file and index metadata
F-->>D: Success
C->>F: Ask for versions of the package
F-->>C: List of available versions
C->>F: Download chosen version
F->>S: Fetch file
S-->>C: Package delivered
C->>F: Ask for a public package not yet in feed
F->>U: Fetch from upstream and save a copy
U-->>F: Package
F-->>C: Package delivered
The publish journey
Build and pack
The library is compiled and tested, and then bundled into a package file with a name and a version number.
Authenticate
The tool sends the package with an access token, so the service knows who is publishing.
Validate
The service checks that the caller may publish to this feed and that this exact version does not already exist.
Store and index
The file is saved and its metadata added to the catalog. From now on, it is immutable.
Announce
The package appears in the feed. Other pipelines and developers can find and use it, often with notifications or automated updates.
The restore journey
Restore is the step where a build downloads all the packages it needs before compiling. The package manager first reads the project’s list of dependencies and its configured feeds. It then asks each feed for the available versions, resolves the dependency tree, downloads missing files, and stores them in a local cache on the build machine. Later builds on the same machine find them in the local cache, which is faster.
Where each delay comes from
- First restore on a fresh machine: every package must be downloaded, so it is the slowest.
- First request for a new public package: the feed must fetch it from upstream before serving it, adding a short extra delay once.
- Repeated restores: served from the feed or the local cache, which is quick.
A new employee’s first day needs a full toolkit handed out from the warehouse. Later days only need the tools that are missing or updated. If the toolkit has a part the warehouse does not stock, the clerk orders it once, shelves a spare, and every later employee gets it instantly.
A pipeline that publishes a fixed version number on every run will succeed once and then fail. Automate version numbers, for example by adding a build counter or tying them to release tags, so each run produces a new, unique version.
9Upstream Sources and Supply Chain Defense
Your product is only as safe as the packages inside it. Upstream rules are your first line of defense.
How upstream works
When you enable an upstream source on a feed, the feed becomes a smart middleman. A developer asks the feed for a public package. If the feed does not yet hold it, the feed fetches the right version from the public registry, saves a copy, and serves it. From then on, that version is served from your feed, even if the public registry is down or the original author deletes it. The feed also shows available public versions, so tools can resolve ranges, although only the versions actually used are copied.
flowchart TD
B["Build asks for a package"] --> Q{"Is the version in the feed"}
Q -->|"yes"| S["Serve from feed storage"]
Q -->|"no"| U["Look in upstream sources in order"]
U --> F{"Found upstream"}
F -->|"yes"| SV["Save copy in feed"]
SV --> S
F -->|"no"| E["Return not found"]
Benefits
Survive outages
Builds keep working when the public registry is unreachable, because used packages are already saved.
Survive deletions
If an author removes a package, your saved copy remains, so your builds do not suddenly break.
One address
Developers configure a single feed address, and the company decides what is reachable behind it.
Know what you use
The saved list shows exactly which public packages and versions your organization has pulled in.
The dependency confusion attack
Imagine your company has a private package called “acme-billing-helper”. An attacker discovers the name, publishes a package with the same name to the public registry, and gives it a very high version number. A poorly configured build asks both places for the latest version, sees that the public one has a higher number, and downloads the attacker’s code into your product. This is called dependency confusion, and it has hit well-known companies.
Azure Artifacts defends against this with a control on each package: whether versions that come from outside are allowed or blocked. When a package name exists in your own feed, outside versions of the same name can be blocked, so a public lookalike is never served. Keep the setting at its protective choice for internal package names, and never let public and private packages with the same name mix.
A mailroom receives two parcels addressed to the same department, one from the company’s known supplier and one from a stranger who claims a newer edition. The mailroom rule says: for items we make ourselves, never accept look-alikes from outside.
Other supply chain risks
- Typosquatting: a malicious package named almost like a popular one, hoping for a typing mistake.
- Compromised maintainers: a trusted public package gets a poisoned update after an account is hijacked.
- Vulnerable versions: an honest package has a security hole discovered later.
- Abandoned packages: something your product depends on is no longer maintained.
Use lock files
Pin exact versions so a surprise new release cannot slip in during a build.
Gate the gateway
Let only a small group save new packages from public sources, and review additions.
Scan dependencies
Run automated checks for known vulnerabilities and unusual licenses during the build.
Keep an inventory
Maintain a list of packages in each release, so that when a hole is announced you know quickly whether you are affected.
In a feed with upstream sources, only identities with at least the collaborator role can cause new public packages to be saved. Giving this role to every build account makes your feed a free-for-all, so grant it with thought.
10Views and Promotion: From Beta to Release
Not every published version is ready for everyone. Views let you stage trust.
The problem views solve
When a team publishes a new version, it is untested by other teams. If every consumer’s build picked it up at once, one bug could break dozens of projects. Teams want a way to say “this version is a candidate” and later “this one is approved for everyone”.
Default views
A feed commonly offers three views. The local view contains every version published to the feed and any version saved from upstream. The prerelease view contains candidate versions. The release view contains versions that have been approved. Consumers who point their tools at the release view only ever see approved versions, and the feed’s view addresses look slightly different from the main feed address.
flowchart LR
PUB["Publish new version"] --> L["Local view: all versions"]
L -->|"passes automated tests"| PR["Prerelease view: candidates"]
PR -->|"approved after review and wider testing"| RL["Release view: approved only"]
RL --> PRODB["Production builds"]
PR --> TESTB["Test and early adopter builds"]
L --> DEVB["Developers on the same team"]
Publish
A new version lands in the feed, visible in the local view to the owning team.
Test automatically
A pipeline runs deeper tests, scans, and license checks against that exact version.
Promote to prerelease
If tests pass, the version is added to the prerelease view, so early adopters can try it.
Promote to release
After feedback and approval, the version joins the release view. Production builds can now use it.
Why promotion is cheap and safe
Promotion adds a label. It does not copy or change the package, so the bytes tested in prerelease are exactly the bytes shipped in release. This avoids the dangerous habit of rebuilding “the same” code for production, which can yield subtly different results.
Views and version labels together
Views describe approval status, while version numbers describe change. A team can publish 3.0.0-beta.1, 3.0.0-beta.2, and so on, as pre-release versions, then publish 3.0.0 as the final. Combining semantic version suffixes with views gives consumers two signals about stability.
A new medicine goes through trial stages before pharmacies can sell it. The same box is moved from the “in trial” shelf to the “approved” shelf. Nobody repacks it. Views are those shelves.
A consumer pointing to the default feed address, not to a view, sees every version, including untested ones. Make sure production builds reference the release view address, and document it for new team members.
11Authentication and Permissions
Who may read, who may publish, and how they prove who they are.
Feed roles
| Role | Can do | Typical holder |
|---|---|---|
| Reader | Search and download packages | Developers who only consume |
| Collaborator | Everything a reader can, plus save packages from upstream | Developers and builds that restore with upstream sources enabled |
| Contributor | Everything a collaborator can, plus publish and promote | Library teams and their release pipelines |
| Owner | Everything, including changing settings and permissions | A small group of feed administrators |
Proving identity from a developer machine
Developers can sign in to package tools in several ways.
Credential providers
A helper plug-in that opens a normal company sign-in window the first time, and then handles tokens automatically. Available for NuGet and .NET tools, and helper tools exist for other ecosystems.
Personal access tokens
A generated secret text with limited permissions and an expiry date. Handy for scripts, but it must be guarded like a password.
Proving identity from a pipeline
Pipelines have their own identity, a build service account. Pipeline steps called authentication tasks, one for each ecosystem, set up the package tool with a short-lived token for that identity, so no secret needs to be stored. For the pipeline to publish or restore, its identity must be granted a role on the feed. If a build fails with “unauthorized” for a feed in another project, the missing role grant is the most common cause.
flowchart TD
P["Pipeline run starts"] --> ID["Pipeline uses build service identity"]
ID --> T["Authentication step creates short lived token"]
T --> TOOL["Package tool uses token"]
TOOL --> F["Feed checks role of the identity"]
F -->|"role allows"| OK["Restore or publish succeeds"]
F -->|"no role"| NO["Unauthorized error"]
Managing tokens safely
- Least privilege: give tokens only the scope they need, such as read-only package access.
- Short life: choose short expiry dates, and rotate before they run out.
- Never in code: do not commit tokens to source repositories or paste them into chat. Use secret variables or a key vault.
- Prefer identities: where possible, use managed or federated identities and sign-in providers instead of long-lived tokens.
- Organization controls: administrators can limit how long tokens may live, or who may create them.
Groups, not individuals
Grant feed roles to groups from your identity system instead of to single people. When someone joins or leaves a team, their access changes automatically with their group membership, which is both safer and easier to audit.
A warehouse badge is better than a copy of the master key. The badge works only at certain doors, expires, and can be cancelled. A personal access token is a numbered key: handy, but if it is lost, anyone who finds it can use it until it expires.
Using a never-expiring full-access token in a shared script, giving every build account contributor rights on every feed, and leaving a former employee’s tokens active.
12Pipeline Integration: Build, Version, Publish, Restore
Packages come alive when pipelines produce and consume them automatically.
A typical library pipeline
Restore
Authenticate to the feed and download the library’s own dependencies.
Build and test
Compile and run unit tests. A failing test stops the pipeline.
Version
Calculate a unique version number, using semantic rules plus a build counter or branch name for pre-releases.
Pack and scan
Create the package file and run security and license scans.
Publish
Push the package to the feed, usually from the main branch or a release tag, not from every experimental branch.
Promote
After tests of consumers pass, add the version to the next view.
flowchart LR
LIB["Library repository"] --> LP["Library pipeline"]
LP --> FD["Feed"]
FD --> AP["Application pipeline restores package"]
FD --> AP2["Another application pipeline"]
AP --> APPA["Application A release"]
AP2 --> APPB["Application B release"]
Choosing version numbers
Good versioning is a team agreement, ideally automated. Many teams keep the major and minor numbers in a file in the repository, and let the pipeline fill in the patch number from the build counter. Builds from side branches get a pre-release suffix that includes the branch name, so experiments never look like official releases. Tags in source control can trigger the final release version.
Making restores fast
Pipeline caching
Save the downloaded packages between runs, keyed by the lock file, so unchanged dependencies are not fetched again.
One feed address
Listing many feeds makes tools query each one in turn. Use one feed with upstreams where possible.
Lock files
Avoid repeating version resolution and avoid surprise upgrades.
Trim dependencies
Each unneeded package adds download time and risk, so remove what you do not use.
Using packages from other places
Azure Artifacts feeds are ordinary registries to ordinary tools, so they also work from GitHub Actions workflows, from developer laptops, from other build systems, and from container builds. In each place you provide the feed address and a suitable sign-in.
Limit publishing to trusted pipelines on protected branches, and grant contributor rights only to those pipelines. A package from a laptop is harder to trace than one built by a controlled, logged pipeline.
13Security: Layers Around Your Packages
A package is code that your product trusts completely. Protect the warehouse and everything that enters it.
flowchart TD
A["Who may use the feed: identity and roles"] --> B["How they sign in: short lived tokens"]
B --> C["What may enter: upstream rules and review"]
C --> D["How it is built: protected pipelines"]
D --> E["What is inside: vulnerability and license scans"]
E --> F["Who changed what: audit logs"]
F --> G["Fast response: inventory and alerts"]
Control who can publish
Publishing rights are powerful. A malicious or careless publish can plant code in many products at once. Restrict contributor roles to release pipelines and a few owners, protect the branches those pipelines run from, and require code review before changes reach them.
Control what comes in
Treat the gateway to public packages as a checkpoint. Limit who can save new public packages, review newly added ones, and block outside versions of your private names. Consider an approval process for packages with unusual licenses or low maintenance.
Scan and inventory
Automated tools can check the full dependency tree for known security issues and risky licenses. Azure DevOps offers security features that include dependency scanning for supported repositories, and many third-party scanners work in pipelines. Keep a record of the exact package versions inside each release, sometimes called a software bill of materials. When a new vulnerability is announced, you can answer “are we affected?” in minutes.
Audit trail
Azure DevOps keeps an audit log of important actions, such as changing feed permissions, creating or deleting feeds, and changing upstream settings. The log can be viewed in the portal and sent to a monitoring system. Review it periodically and set alerts for suspicious changes, like permissions widened late at night.
Network and sign-in policies
Organization-level controls, such as conditional access policies and allowed network ranges, apply to Azure DevOps and therefore protect access to feeds. Combine them with multi-factor sign-in for people.
Strong signs
- Only release pipelines can publish
- Outside versions of internal names are blocked
- New public packages are reviewed
- Lock files and scans are standard
- Audit logs are watched
Warning signs
- Everyone is a contributor on every feed
- Packages are built and pushed from laptops
- Long-lived tokens pasted into scripts
- No record of which versions each release contains
- Nobody owns the feed
A food factory checks suppliers, inspects each delivery, keeps batch records for every product, and can recall exactly the affected batches when a problem is found. Your package process needs the same traceability.
14Reliability, Scalability and Performance
Builds stop when the warehouse is closed. Plan so that one failure does not halt your whole company.
Availability of the service
Azure Artifacts is part of a Microsoft-run cloud service with a published availability promise, called a service level agreement. The platform stores data redundantly and recovers from machine failures on its own. No service is perfect, though. Occasional incidents on Azure DevOps will affect pipelines and feeds, and your design should make them survivable.
Upstream caching as resilience
One of the best protections is already built in. Public packages saved in your feed keep serving even if the public registry is offline. The weak spot is a package version you have never used before, which cannot be fetched during a public registry outage. Teams with strict needs pre-warm the feed by restoring their common dependencies after each approval, so nothing is fetched for the first time during an emergency.
Local and build-agent caches
Package managers keep a local cache on each machine. Build agents that are re-created for every run lose this cache, so use pipeline caching or agents that keep their cache between runs. A warm cache lets builds proceed even if the feed is briefly unreachable, because the needed files are already on the machine.
Throttling and fair use
Azure DevOps protects itself with rate limits. A build farm that starts hundreds of jobs at once, each downloading thousands of small files, can hit “too many requests” responses and slow down. Spread the load, enable caching, trim unused dependencies, and make scripts retry politely with increasing waits.
Cache everything reasonable
Pipeline caches, local caches, and upstream-saved copies mean most requests never go far.
Retry with backoff
Temporary errors are normal. Wait and try again before declaring failure.
Know your emergency path
Decide how critical hotfix builds could proceed if the service is down, such as using a pre-populated cache on a build machine.
Keep sources recoverable
Because packages are built from source, the real insurance is a repository and pipeline that can rebuild any version.
Large packages
Very large files, such as machine learning models, are best shared as Universal Packages, which upload and download in chunks and reuse unchanged pieces between versions. Even so, big downloads are slow on poor links. Place build agents close to the service, cache large downloads, and avoid pulling them on every run.
Scaling with the organization
As the number of packages and consumers grows, the main challenges are human, not technical: naming rules, ownership, cleanup, and discoverability. Write a short package policy covering naming prefixes, version rules, who owns each feed, and how to deprecate packages. A large catalog without ownership turns into a junk drawer.
The feed holds copies of built outputs, but your source code and pipeline definitions are the real recipe. If everything in a feed were lost, you could rebuild your own packages from source, and public packages could be fetched again. Make sure that rebuilding is actually possible, and test it.
15Monitoring, Retention and Cost
A warehouse that never throws anything away eventually fills the building. Watching usage and cleaning up keeps it healthy and affordable.
What to watch
Size over time
Azure DevOps shows how much storage the organization uses and which feeds use the most. Check it regularly so growth is never a surprise.
Pipeline errors
Failed restores and publishes show up in pipeline results. A sudden rise in unauthorized or not-found errors often means a permission or upstream change.
Audit events
Permission changes, new upstream sources, and deleted feeds are recorded and can be reviewed or exported.
Who uses what
Package pages show download counts and the versions consumers actually use, which helps decide when an old version can be retired.
Retention policies
Continuous publishing creates many versions. Most are never used again after a newer one appears. A retention policy automatically removes the oldest versions beyond a number you choose for each package. Versions that have been promoted to a view are normally kept, so the approved ones that real products use are safe from cleanup. Choose the number with care: keep enough history to roll back and to rebuild older product releases.
The recycle bin
Deleted package versions move to a recycle bin for a limited time before being permanently removed. This gives a safety net for mistakes. Remember, though, that once a version is truly gone, its number cannot be reused for different contents, so consumers who needed it must move to another version.
Cost awareness
Azure Artifacts offers a free allowance of storage for each organization, and usage above it is billed according to Microsoft’s current pricing. Because prices and allowances change, check the official pricing page for today’s numbers. What stays true is the cost drivers: total stored size, number of retained versions, and big files like Universal Packages or large binaries.
| Cost driver | Why it grows | How to control it |
|---|---|---|
| Many old versions | Every pipeline run publishes a new one | Retention policies, and publish only from main or release branches |
| Large binaries | Models, installers, or media in packages | Store only what must be versioned, and compress files |
| Abandoned feeds | Old projects keep their packages forever | Assign owners, review yearly, archive or delete |
| Upstream copies | Every used public version is saved | Remove unused dependencies and old saved versions |
A pantry needs a regular check. Keep the staples and recent items, discard the expired cans, and write down what you actually use. Without that, you pay for shelf space full of things nobody will ever eat.
16Design Patterns and Anti-Patterns
Ways of organizing feeds that experienced teams repeat, and traps that they learned to avoid.
Pattern: one organization feed with upstreams
A single organization-wide feed with public upstreams gives every team one address, one set of rules, and one cache. It suits small to medium companies where teams share most libraries.
Pattern: team feeds plus a shared gateway feed
Each team has its own feed for its internal libraries, and each team feed uses one shared “gateway” feed as an upstream. The gateway feed is the only one connected to public registries and is managed by a platform team. Teams get independence, and the company gets a single controlled entrance.
flowchart TD
PUBR["Public registries"] --> GW["Gateway feed managed by platform team"]
GW --> TA["Team A feed"]
GW --> TB["Team B feed"]
GW --> TC["Team C feed"]
TA --> BA["Team A builds"]
TB --> BB["Team B builds"]
TC --> BC["Team C builds"]
TA -.->|"upstream of other feeds if allowed"| TB
Pattern: promotion by views
Every library publishes once, then moves through prerelease and release views. Consumers choose their level of risk by choosing a view.
Pattern: build once, promote the same bits
Never rebuild for production. The package tested is the package shipped.
Anti-patterns
Do this
- Use a gateway or upstream-enabled feed
- Name internal packages with a company prefix
- Automate versions and publishing
- Give roles to groups
- Assign an owner to every feed
Avoid this
- Letting each developer add their own package sources
- Publishing manually from laptops
- Reusing a version number for new contents
- Putting secrets, such as passwords, inside packages
- Using a feed as a general file dump
Decision: use a single gateway feed for all public packages
Context: Teams each configured their own package sources, causing inconsistent versions, hidden risk, and long restore times.
Decision: A platform team owns one gateway feed with public upstreams. All team feeds use it as their only upstream.
Consequences: One place to review, block, and audit public packages. A small approval step adds slight delay for brand-new dependencies, which the team accepts for the safety gained.
17Best Practices and Common Mistakes
A checklist you can adopt on the first day, and a list of stumbles to skip.
Best practices
Choose scope on purpose
Prefer project-scoped feeds for team libraries, and organization-scoped for truly shared ones. Decide before creating feeds, since changing later is awkward.
Write naming rules
Use a consistent prefix or namespace for internal packages so they are easy to find and impossible to confuse with public ones.
Follow semantic versioning
Major for breaking changes, minor for new features, patch for fixes. Consumers rely on this promise.
Automate the lifecycle
Pipelines build, version, scan, publish, and promote. Humans review and approve.
Protect the entrance
Control upstream additions, block lookalike names, and use lock files.
Use least privilege
Readers by default, contributors only for release pipelines, owners for a small group.
Clean up on a schedule
Retention policies, yearly feed reviews, and a plan for deprecated packages.
Document for newcomers
A one-page guide with the feed address, how to sign in, how to publish, and who to ask.
Common mistakes
| Mistake | What happens | Better approach |
|---|---|---|
| Mixing private and public packages without blocking rules | Dependency confusion risk | Block outside versions for internal names |
| Hard-coded version number in the pipeline | Second publish fails | Generate a unique version per run |
| Build account lacks feed permission | Unauthorized errors, especially across projects | Grant the build identity the right role |
| Long-lived token in a repository | Anyone with repo access gets feed access | Use pipeline authentication and secret stores |
| Pointing production to the default feed view | Untested versions get used | Use the release view address |
| Treating Artifacts as a container registry | Container images cannot be stored | Use Azure Container Registry for images |
| Never cleaning up | Growing bills and clutter | Retention policies and ownership |
Famous incidents in the wider industry show that when a widely used tiny package disappears, thousands of builds break. Saved upstream copies and pinned versions are your protection. Never assume that something is permanently available just because it was available yesterday.
18Real-World Scenarios
These are composite examples that show typical situations. They are illustrations, not reports about specific companies.
Scenario 1: A shared UI component library
Situation: A retail company has six web applications that all need the same buttons, forms, and color rules. Developers were copying files between repositories and they had drifted apart.
Solution: The design team publishes the component library as an npm package to a project feed. Application teams install a specific version. Fixes are made in one place, released as a new version, and consumers upgrade when ready.
Result: Consistent appearance, faster fixes, and clear version history.
Scenario 2: Protecting a bank-style build from outages
Situation: A financial services team lost a day when a public registry had an outage during a release.
Solution: They moved all restores through a feed with upstreams, locked dependency versions, and added a nightly job that restores every product so that all used packages are saved in the feed in advance.
Result: Later registry hiccups did not stop releases.
Scenario 3: Sharing .NET libraries across many services
Situation: A logistics company has dozens of microservices that share logging, security, and messaging libraries.
Solution: Library teams publish NuGet packages with semantic versions. Prerelease versions are tested by two pilot services, then promoted to release. A dependency update tool opens automatic update requests in service repositories.
Result: Services stay current, and breaking changes are spotted in pilots before everybody receives them.
Scenario 4: Shipping large data files with software
Situation: A data science group needs to version trained models of several hundred megabytes together with their applications.
Solution: Models are published as Universal Packages with version numbers matching the application release. Pipelines download only the version they need.
Result: Reproducible releases and no binary files stuffed into source repositories.
Scenario 5: Responding to a newly announced vulnerability
Situation: A widely used library is announced to have a serious flaw.
Solution: Because the company keeps a list of package versions inside each release, security staff query the list and find three affected services within the hour. Fixed versions are published to the feed, promoted, and pipelines rebuild the services.
Result: Quick, targeted response instead of a company-wide scramble.
19Azure Artifacts Compared with Related Tools
Several tools store build outputs. Knowing which does what avoids wasted effort.
| Tool | Best for | Key difference |
|---|---|---|
| Azure Artifacts | Reusable libraries and packages across projects | Versioned, shared, with upstreams and views |
| Pipeline artifacts | Passing build output between stages of one pipeline run | Tied to a run, temporary, not a shared registry |
| Azure Container Registry | Container images and related artifacts | Speaks the container protocol, which Artifacts does not |
| GitHub Packages | Packages close to GitHub repositories | Integrated with GitHub permissions and Actions |
| Third-party repository managers | Organizations that want one tool across many clouds and formats | Often broader format support, separate to run or buy |
| Azure Blob Storage | Raw file storage | No package semantics such as versions or dependency lookup |
flowchart TD
Q["What are you storing"] --> A{"Container image"}
A -->|"yes"| ACR["Azure Container Registry"]
A -->|"no"| B{"Reusable package for other projects"}
B -->|"yes"| ART["Azure Artifacts feed"]
B -->|"no"| C{"Only passed between stages of one pipeline"}
C -->|"yes"| PA["Pipeline artifacts"]
C -->|"no"| BLOB["Blob storage or another store"]
When to look elsewhere
- If your code and workflows live in GitHub, GitHub Packages may be simpler.
- If you need package formats Azure Artifacts does not offer, a third-party repository manager may fit.
- If you run Azure DevOps Server on your own machines, remember it is a separate product with its own feature set and versions, so check its documentation.
Supported package types, limits, and pricing change over time. Before making a final design decision, confirm them on Microsoft’s current documentation pages.
20Frequently Asked Questions
It is a managed package repository inside Azure DevOps where teams store, share, and control versioned libraries and other packages.
No. It supports NuGet, npm, Maven, Gradle, Python, Cargo, and Universal Packages, so many languages can share one service.
No. Container images belong in a container registry such as Azure Container Registry.
A feed is the shelf or catalog. A package is one item, with many versions, stored on that shelf.
No. Published versions are immutable. Fix the problem and publish a new version. You may unlist or delete a bad version, but its number cannot be reused for different contents.
It lets your feed fetch packages from a public registry or another feed, save a copy, and serve it from your own feed afterward.
Block outside versions of your internal package names, use a distinctive naming prefix, pin versions with lock files, and limit who can save new public packages.
They label versions by readiness, such as prerelease and release, so consumers can choose how much risk they accept without copying packages around.
The most common reasons are that the build identity has no role on the feed, the authentication step is missing, or the feed lives in another project and the identity was never granted access.
Use project feeds when packages belong to one team’s work and should follow that project’s permissions. Use organization feeds for packages that many projects share. Decide early.
There is a free storage allowance, and usage beyond it is billed. Check Microsoft’s pricing page for current amounts.
Feeds can be opened to chosen users or, in public projects, to wider audiences, depending on organization settings. By default, treat feeds as private and grant access deliberately.
Pipeline artifacts carry files between stages of one run and expire. Azure Artifacts packages are long-lived, versioned, and shared across projects and teams.
If your feed already saved that version from upstream, you can still use it. If not, you cannot fetch it. That is why saving through upstreams and pre-warming matter.
No. Create a feed, publish one small package from a pipeline, consume it from another project, and you have learned the core loop. The rest is policy and good habits.
21Summary and Key Takeaways
Azure Artifacts turns scattered code copies into a controlled, versioned supply of building blocks.
You began with a simple idea: a good workshop keeps a labeled parts warehouse instead of letting every craftsperson make their own copies. Azure Artifacts is that warehouse for software. Feeds hold packages, packages hold immutable versions, upstream sources bring in public packages safely, and views let you promote trust step by step. Authentication, roles, and pipelines connect all of it to everyday work, while retention, monitoring, and clear ownership keep it tidy and affordable.
The deeper lesson is about trust. Every package you use is code you did not write running inside your product. The practices in this guide, such as pinned versions, blocked lookalikes, reviewed additions, protected pipelines, inventories, and audit logs, are how you keep that trust earned rather than assumed.
Key Takeaways
- Azure Artifacts is a managed package repository in Azure DevOps supporting NuGet, npm, Maven, Gradle, Python, Cargo, and Universal Packages.
- Published versions are immutable, so every release can be trusted and reproduced; fix mistakes by publishing a new version.
- Upstream sources save copies of public packages, which improves resilience, but block outside versions of your internal names to prevent dependency confusion.
- Views promote the same package from prerelease to release without copying, and production should only use the release view.
- Use group-based roles, pipeline identities, and short-lived tokens, and publish only from protected, automated pipelines.
- Plan for retention, cost, and ownership early, and keep an inventory of package versions in every release.
- Use Azure Container Registry for images and pipeline artifacts for temporary stage handoffs; always confirm current limits and prices on Microsoft’s pages.