Skip to content
CAMPUX Cloud Bootcamp Phase Four · Class Thirty-Nine
Phase Four — Operate, Secure & AI
Reading 12 min · Drills 4 · Part III of IX
Class Thirty-Nine · Pipelines
Class Thirty-Nine · Part III

Agents & pools — the machines that run the work

A pipeline is only a description of work until something picks it up and runs it; this part is about that something — the machine your job actually lands on, who patches it, and the short, honest list of reasons to ever run one yourself.

§1

The pipeline describes the work; the agent does it

A YAML file is a set of instructions, and instructions do nothing on their own. Somewhere a physical or virtual machine has to check out your code, run the compiler, execute the tests, and push the result — and that machine is the agent. An agent is computing infrastructure with the Azure Pipelines agent software installed on it; it runs one job at a time, and when your pipeline starts a job, the system hands that job to an available agent to actually carry out. Everything you wrote in 39b was a description; the agent is where the description becomes real, and it is the part beginners forget exists until a build sits queued for twenty minutes waiting for one to come free.

Agents do not float loose; they are grouped into pools. A pool is a named collection of agents, and a pipeline job targets a pool rather than a specific machine, so that whichever agent in the pool is free picks the job up. When you wrote pool: with vmImage: ubuntu-latest in 39b, you were pointing the job at the built-in Azure Pipelines pool — Microsoft's own fleet — and asking for a fresh Ubuntu machine from it. You never named a server, because you never had to: the pool is the abstraction that lets you ask for "a Linux machine" instead of owning one.

Someone runs the machine. Decide who.

Agent
A machine — physical, virtual, or a container — running the Azure Pipelines agent software, which runs exactly one pipeline job at a time. A pool is a group of interchangeable agents a job targets by name; the system routes each job to a free agent in the pool.
§2

Microsoft-hosted or self-hosted — who owns the machine

There are two kinds of agent, and the whole of this part turns on the difference between them, because it is really a question about who is responsible for the machine. A Microsoft-hosted agent is a machine Microsoft owns, patches, and hands you fresh. Each time your pipeline runs, you get a brand-new virtual machine for each job; the job runs; and the machine is discarded the moment the job finishes. Anything the job wrote to disk — the checked-out code, a cached dependency, a leaked secret — is gone with it, because the next job starts on a different, clean VM. You never log in, never patch it, never see it. Maintenance and image upgrades happen automatically, and you always get the latest version of the image you named.1

A self-hosted agent is the opposite trade. It is a machine you provide — a VM in your subscription, a box under a desk, a container you run — on which you install the agent software yourself. It persists between runs, which is both its point and its price: caches and installed tools carry over from job to job, so builds can be faster, but nothing gets patched, cleaned, or hardened unless you do it. The machine is now yours to own, forever, with everything that word implies — operating-system updates, disk space, the tools your pipelines assume are present, and the security of a box that, by design, runs whatever your pipelines tell it to.

Hold the two side by side before you choose. The table below is the honest ledger of what you are trading, and the column that quietly matters most is the last one.

Table 1 — Microsoft-hosted vs self-hosted agents, the trade in full
 Microsoft-hostedSelf-hosted
Maintenance & patchingMicrosoft's; automatic image upgrades, fresh VM per job, nothing for you to updateYours; OS updates, agent version, disk, and installed tools are all your standing chore
Network reachRuns on public Microsoft infrastructure; reaches private resources only through extra plumbing you buildSits inside your own network, so it can reach private endpoints and on-prem systems directly
Custom / licensed softwareThe image is what it is; anything extra is installed per run, costing minutes every timeInstall once and it persists — the right home for large toolchains and licensed software
Cost modelConcurrency-based parallel jobs; a free tier you enable, paid beyond it; no machines to runNo per-minute charge for the agent, but you pay to run, store, and secure the machine yourself
Security burdenClean per-job VM discarded after use; blast radius resets every runA persistent box that runs arbitrary pipeline code — patch, isolate, and least-privilege it like any exposed host

Read the table as a default and an exception. The default is Microsoft-hosted: a clean machine, maintained by someone else, with the blast radius reset after every job, is the correct choice for almost every workload almost all of the time. The exception is self-hosted, and it earns its keep only when one of a short list of real needs applies — which is the subject of §4.

§3

Capabilities, demands, and the parallelism grant

Once you run your own agents, you need a way to send the right job to the right machine, and Azure Pipelines does it with a matching game. Every self-hosted agent publishes a set of capabilities — name/value pairs describing what it can do. Some are system capabilities the agent discovers on its own (operating system, machine name, versions of installed software, environment variables); others are user capabilities you add by hand to tag a machine — say, that it holds a particular licensed tool. A pipeline job then states its demands, and the system routes the job only to an agent in the pool whose capabilities satisfy those demands. Demand SpecialSoftware and your job will wait for — and only ever land on — a machine that advertises it.

Capabilities and demands are a self-hosted concern by design. With Microsoft-hosted agents you do not tag machines; you simply select the image that matches your job's needs, and the fleet gives you one. The mechanism exists precisely because self-hosted agents are heterogeneous — your machines differ — and the pool needs a way to honour those differences without you hard-coding a server name into the pipeline.

The second thing you meet the moment you run real work is the parallel job — the unit of concurrency. One parallel job lets one pipeline job run at a time; buy or earn more and more can run at once. Parallel jobs are set at the organisation level and shared across every pipeline in it, and here is the part that surprises new organisations: Microsoft-hosted parallelism is not simply switched on for free. The self-hosted free tier is granted automatically, but the Microsoft-hosted free tier must be enabled — you link your Azure DevOps organisation to a valid Azure subscription (set up billing), and only then does the free grant apply: one job, up to sixty minutes per run, capped at 1,800 minutes a month.2 Until you do that, a brand-new org can find its first pipeline stuck with "no hosted parallelism" and no obvious reason why — a five-minute fix that costs an afternoon if you do not know it exists.

§4

When to self-host — the honest short list

Self-hosting an agent is taking on a maintenance liability, so the bar for doing it should be a genuine need, not a habit or a hunch that it will be "cheaper" or "more control." There is a short list of reasons that actually clear the bar. Learn it as a checklist, because in an interview and on the job the valuable move is not "I can set up a self-hosted agent" — anyone can — it is knowing the four or five cases where you should, and defaulting to hosted everywhere else.

Private-network reach
The deploy target has no public endpoint — a database behind a private link, an on-prem system, a resource reachable only from inside your VNet. A self-hosted agent that lives in that network can reach it; a Microsoft-hosted one cannot without extra plumbing. This is the most common legitimate reason by far.
Specialised or licensed software
Your build needs a large toolchain, a specific SDK, or licensed software that is expensive or slow to install fresh every run. Install it once on a machine you keep, and every job starts with it already present.
Large caches or artifacts
Builds that lean on a big dependency cache or a heavy working set benefit from a machine whose disk persists between runs, rather than re-downloading gigabytes onto a clean VM each time.
Specific hardware
The job needs more CPU, memory, GPU, or a particular architecture than the hosted images offer. You control the machine's size and shape when it is yours.

Notice what is not on the list: "it feels cheaper," "we want control," "we already have a spare VM." Those are how estates accumulate unpatched, forgotten agents. And note the sting in the tail of every reason above: a self-hosted agent runs whatever your pipelines tell it to, on a machine that persists, often with a line into your private network — which makes it exactly the kind of standing, powerful host you learned to distrust with self-hosted GitHub runners back in Class Twenty-Four. The instinct is identical: patch it, isolate it, scope its permissions to the least it needs, and never let a long-lived agent hold more access than the job in front of it requires. A self-hosted agent is a tool you reach for deliberately, keep short, and secure like the liability it is.

Case File · Campux Retail

The 2019 agent nobody had logged into

where the warehouse deploy runs — and the one machine that had to go

Settling where Basecamp's pipelines run turns up a machine everyone had forgotten: a self-hosted agent VM stood up in 2019, still registered, still picking up the warehouse deploy, and — the reader confirms with a wince — not patched since roughly the year it was built. It sits inside Basecamp's own network, which is precisely why it was ever created: the warehouse system it deploys to has no public endpoint, so a Microsoft-hosted agent genuinely cannot reach it. The private-network reason is real; the 2019 machine is not the way to honour it.

So the reader splits the decision. The warehouse deploy keeps a self-hosted agent, because the need is legitimate — but the old VM is retired and replaced with a fresh one: current OS, latest agent, locked into an isolated subnet with a network path to the warehouse and nothing else, and a least-privilege identity that can deploy to that one target and go no further. Every other pipeline in the acquired estate — the storefront builds, the internal tooling, the reporting jobs, none of which needs private reach — is moved onto Microsoft-hosted agents, so their machines are Microsoft's problem and their blast radius resets every run. One self-hosted agent, kept for one honest reason and secured like the exposed host it is; everything else handed back to the fleet. The subscription-wide azure-prod secret is noted and left alone — it is a credential problem, and its reckoning waits for 39i.

On the job

"Why is the build queued for twenty minutes?"

You · Cloud Engineer · the morning the pool runs dry

A team lead pings you: builds are crawling, everything sits "queued." You open the pool consumption report and see it at once — every parallel job is in use and the rest are lined up behind them. It is not a broken pipeline; it is a capacity wall. You have two honest levers and you name both: buy more parallel jobs so more can run at once, or find the one slow job hogging an agent and split or speed it. What you do not do is quietly stand up a self-hosted agent to "get around the limit" — that trades a visible cost for an invisible, unpatched liability, and it is the exact instinct §4 is warning you against. The seniority is diagnosing the constraint out loud, not smuggling in a machine nobody will remember to maintain.

§5

Why this part is worth more than it looks

Agents feel like plumbing — the boring layer beneath the pipeline you actually wrote — and that is exactly why understanding them marks you out. Most engineers can write a YAML pipeline; far fewer can explain, calmly, why the build is queued, what a pool actually is, or why the innocent-looking self-hosted agent someone added last year is now the softest target in the estate. Those are the questions a senior asks in an interview precisely because they separate people who copied a pool: line from a sample from people who know what it points at.

Carry three sentences out of here and you can hold that conversation. Hosted is the default: a clean machine you do not maintain, discarded after every job. Self-hosted is a deliberate exception, taken only for private-network reach, specialised software, big caches, or specific hardware — and secured like the exposed, long-lived host it is. And parallel jobs are the concurrency you buy or enable, the reason a queue forms and the honest lever when it does. Know those, and "where does the work actually run?" stops being a gap and starts being a thing you can draw.

Class 39c

Examination

Four drills, then two situations. Write your answer before you reveal the reasoning, or the exercise is worthless. Nothing is stored.

Drill 01Recall
Your job runs on a Microsoft-hosted agent, checks out code, and writes a large cache to disk. The next job in the next run starts — what is true of that cache?
Marked

B — the fresh-VM-per-job model is the whole point of Microsoft-hosted. Each job gets a brand-new virtual machine, and that machine is discarded the moment the job finishes, so anything written to its file system — a cache, checked-out code, a leaked token — is gone before the next job starts on a different clean VM. This is a feature, not a limitation: it is why the blast radius resets every run and why you never patch these machines. A describes a self-hosted agent, whose persistence is exactly what makes caches carry over — and exactly what makes it a standing security liability. C invents a maintenance step you never perform on hosted agents; Microsoft patches them. D invents an OS split that does not exist. If you need the cache to survive, you use the pipeline's caching feature or a self-hosted agent — you do not assume the disk is still there.

Drill 02Recall
A pipeline must deploy to a database that has no public endpoint — it is reachable only from inside your virtual network. Which agent choice actually solves this, and why?
Marked

B — private-network reach is the single most common legitimate reason to self-host. A Microsoft-hosted agent runs on public Microsoft infrastructure and cannot reach a resource with no public endpoint without extra plumbing; a self-hosted agent living inside your VNet reaches it directly, which is precisely why the need justifies the maintenance cost here. A is the right default in general but wrong for this specific requirement — the default yields to a genuine need. C is the dangerous half-truth: self-hosted agents are not inherently more secure — they are a persistent host running arbitrary pipeline code, so they carry more security burden, not less; you pick one here despite that, and then patch and isolate it. D is simply false: network location is the entire point. The discipline is choosing self-hosted for the real reason and then treating the machine like the exposed host it is.

Drill 03Select three
Which three are true of agents, pools, capabilities, and parallel jobs on Azure DevOps?
Marked

Pools route jobs to free agents; capabilities and demands are the self-hosted matching game; the hosted free tier must be enabled by linking a subscription. Those three are the load-bearing facts. The two rejects are the confusions that cost new organisations an afternoon. Microsoft-hosted parallelism is not automatic — the self-hosted free tier is granted for you, but the hosted one you must switch on by setting up billing against a valid Azure subscription, and until you do, a fresh org's first pipeline can sit with no hosted parallelism and no obvious reason. And an agent runs exactly one job at a time — concurrency comes from having more parallel jobs and more agents, not from one machine doing several at once; believing otherwise is how people misread a queue as a broken pipeline.

Drill 04Spot the error
An engineer proposes this agent plan for a new team. One line is the reasoning this part exists to stop. Which?
# agent plan — new product team
1.  Default all builds to Microsoft-hosted agents;
    let Microsoft patch and discard the machines.
2.  We have a leftover VM spare, so let's register it
    as a self-hosted agent to save a bit of money —
    no particular need, it's just sitting there.
3.  The one deploy that hits an on-prem system keeps a
    self-hosted agent, patched and in an isolated subnet.
4.  Enable the Microsoft-hosted free tier by linking
    our Azure subscription before the first run.
Marked

Line two — "no particular need, it's just sitting there" is exactly the reason that is not on the list. A self-hosted agent is a persistent machine that runs arbitrary pipeline code; standing one up without a genuine need buys you an unpatched, forgotten host — the softest target in the estate — to save an amount of money that rounds to nothing. That is how the 2019 agent in the case file came to exist. The other lines are the part done right: hosted as the default because the machines are Microsoft's problem and reset every run (A inverts it — self-hosting everything multiplies the liability); a self-hosted agent kept for the honest reason of private-network reach and then patched and isolated (C misreads the one legitimate case); and enabling the hosted free tier by linking a subscription, which a new org genuinely must do (D is false — hosted parallelism is not automatic). The rule: self-host for a named need on the short list, or not at all.

Situation 01Write before you reveal
A teammate wants to move all builds onto a self-hosted agent "for speed and control — the hosted ones feel slow and we'd own the machine." The builds have no private-network need. What do you advise, and what would actually change if you agreed?
"Speed and control" are feelings, not the short list. Price the maintenance and security you would be signing up for against the thing you would actually gain.
Reasoning

The trap is that "speed and control" sound like reasons but are not on the list. The honest short list for self-hosting is private-network reach, specialised or licensed software, large persistent caches, or specific hardware. "Feels slow" and "we'd own it" are none of those — and owning the machine is the cost, not the benefit. Name that first: you are not being offered a faster build, you are being offered a maintenance liability with a vague upside.

Price both sides concretely. Move to self-hosted and you take on OS patching, agent upgrades, disk management, and — the part that bites later — the security of a persistent box that runs arbitrary pipeline code, which now needs to be patched, isolated, and least-privileged like any exposed host. Against that, the "speed" is usually solvable without any of it: if a slow build is the real complaint, the cause is a slow stage or a queue, not the fleet — and the fix is caching, splitting the job, or buying another parallel job, all of which keep the machine Microsoft's problem.

Redirect to the real question. Ask what "slow" actually means and open the pool consumption report. If builds queue, it is a parallelism wall — buy capacity. If one build is slow, profile and cache it. Agree to self-host only if a genuine need from the list appears; until then, the default stands. You have honoured the goal — faster, smoother builds — while refusing to pay for it with an unpatched agent nobody will remember exists in a year.

Situation 02Write before you reveal
You inherit a self-hosted agent that has quietly run the warehouse deploy since 2019, unpatched, inside the network. The deploy genuinely needs private-network reach. A colleague says "it works, leave it." What do you do, and how do you justify it?
Separate the two questions hiding in one machine: does the deploy need a self-hosted agent at all, and is this agent an acceptable one?
Reasoning

The move is to split one decision into two. "It works, leave it" collapses two separate questions: should this deploy use a self-hosted agent? and is this particular 2019 machine acceptable? The first answer is yes — the warehouse system has no public endpoint, so private-network reach is a real, listed reason, and a Microsoft-hosted agent genuinely cannot do the job. Concede that plainly so the colleague knows you are not on a hosted-everything crusade.

Then reject the machine, not the approach. An unpatched host that has run arbitrary pipeline code inside your network since 2019, with a line to a production system, is exactly the standing liability this part warns about — the same suspicion you learned to apply to self-hosted runners in Class Twenty-Four. "It works" describes function, not safety; the machine can work perfectly and still be the softest way into the warehouse. The need is legitimate; this instance of meeting it is not.

Replace, do not remove. Stand up a fresh agent — current OS, latest agent software, an isolated subnet with a path to the warehouse and nothing else, and a least-privilege identity scoped to that one deploy. Cut the old VM over and retire it. The warehouse keeps its private reach; the estate loses an unpatched host it had forgotten it owned. Framed for the colleague: we are not changing how the warehouse deploys — we are changing which machine is trusted to do it, because "it works" was never the same as "it is safe."

Examination record · first attempt
0/4
Class 39c · Complete
Retain this much

Five things worth carrying out of this part

  1. An agent is the machine that runs a job — one job at a time; a pool is a group of agents a job targets by name, so a free one picks it up. Your pool: vmImage: ubuntu-latest pointed at Microsoft's fleet.
  2. Microsoft-hosted agents are a fresh, clean VM per job, discarded after, patched and maintained by Microsoft — no state survives. Self-hosted agents are machines you own, run, and patch, whose persistence is both the benefit and the liability.
  3. Hosted is the default. Self-host only for a named need: private-network reach, specialised or licensed software, large persistent caches, or specific hardware — and secure the machine like the exposed, long-lived host it is.
  4. Capabilities and demands match jobs to self-hosted agents; with hosted agents you pick an image instead. An agent runs one job at a time — concurrency is a matter of parallel jobs and more agents.
  5. Microsoft-hosted parallelism is not automatic: enable the free tier by linking the org to an Azure subscription (one job, up to 60 minutes, capped monthly). The self-hosted free tier is granted for you.
Notes
  1. Azure Pipelines also offers agent types beyond the two this part contrasts — GitHub-hosted agents (pay-as-you-go, more powerful machines), Managed DevOps Pools (a fully managed service where the machines live in a Microsoft subscription), and Virtual Machine Scale Set agents (autoscaling self-hosted). They are variations on the same hosted-versus-self-hosted axis, not exceptions to it. Learn the two poles here; reach for the others only when a specific need names them, and check the current option list on Microsoft Learn before you commit.
  2. Treat the exact free-tier numbers and the enablement mechanism as things to confirm, not memorise — they have moved before. For years new organisations had to request Microsoft-hosted parallelism through a support form; today you enable it by linking the org to a valid Azure subscription, and the grant is one hosted job at 60 minutes per run with a 1,800-minute monthly cap. The settled direction is what matters: hosted parallelism is not switched on automatically, and a new org must do something to get it. Verify the current figures and steps on Microsoft Learn before you rely on them.