Build Queue Management in Jenkins
Every build waits for its turn. Learn how the Jenkins queue works, why builds get stuck, how to give the right work to the right machines, and how to keep waiting times short as your team grows.
Imagine a popular coffee shop at eight in the morning. Customers line up at the counter, each with a different order. Some want a quick espresso, and some want a complicated drink with three modifications. There are only three baristas, and every one of them is busy. The line grows, people start to look at their watches, and someone at the back asks, “Why is nobody moving?”
A Jenkins build queue is that line. Every time a developer pushes code, a schedule fires, or a person clicks the build button, a request joins the queue and waits for a worker machine to become free. When the queue is short, nobody notices it. When it grows, developers wait for feedback, releases slip, and the phrase “Jenkins is slow” spreads through the company. Managing the queue means making sure the right work reaches the right workers at the right time, and that the line never grows out of control.
In this guide you will learn what the build queue is, how items move through it, why builds sometimes wait far longer than expected, how executors and labels decide where work runs, how to control concurrency, priorities, and cloud agents, and which mistakes cause the most delays. We assume you know nothing about Jenkins yet, and we explain each new word the first time it appears.
1What Is the Build Queue?
The build queue is the waiting line where Jenkins keeps every build request until a machine is ready to run it.
First, the basics
Jenkins is a free automation server that builds, tests, and delivers software. A build is one run of a job: fetch the code, compile it, run the tests, and report the result. Builds do not run on the main Jenkins server. They run on worker machines called agents. Each agent can run a limited number of builds at the same time, and each slot that can run one build is called an executor.
What is the queue?
When a build is requested but no executor is free, Jenkins cannot start it immediately. It places the request in the build queue. The queue appears on the left side of the Jenkins home page, listing the jobs that are waiting and the reason each one waits. As soon as a suitable executor becomes free, Jenkins takes the next eligible item out of the queue and starts the build.
Who puts items in the queue?
- People who click the build button.
- Code changes reported by webhooks or found by polling.
- Schedules that start jobs at fixed times.
- Other jobs that trigger downstream jobs after they finish.
- Automation that calls the Jenkins web interface from scripts and tools.
Think of a hospital emergency room. Patients arrive from many directions: ambulances, walk-ins, referrals. A triage desk writes each one on a list. Doctors and beds are limited, so the list decides who is seen next. The build queue is the triage list, executors are the beds, and the scheduler is the nurse who matches patients to beds.
Why queue management matters
Every minute a build waits is a minute a developer waits. Long queues slow feedback, encourage people to batch changes into larger and riskier ones, and create pressure to skip tests. Managing the queue well is one of the most direct ways to make a whole engineering team faster.
A queue is not a problem by itself. A short queue means the system is being used well. The problem is a queue that keeps growing, or an item that waits for a reason nobody understands.
2Why It Exists: The Problem and the History
Any system with limited workers and unlimited requests needs a queue. Build servers are no exception.
The early days
The first Jenkins installations were small. One server ran a handful of jobs, and each build started the moment it was requested. As teams added more jobs, more developers, and more tests, builds began to overlap. To keep the server from collapsing under too many simultaneous builds, Jenkins introduced executors, which cap how many builds run at once, and the queue, which holds the rest.
The move to many agents
Soon one machine was not enough. Jenkins gained the ability to distribute builds across many agents, each with its own tools and operating system. That created a new question: not only “is there a free executor?” but “is there a free executor on a machine that can run this particular job?” Labels and matching rules grew out of that need.
The cloud era
Later, agents became disposable. Instead of a fixed set of machines, Jenkins can create agents on demand in the cloud or in a container platform, and remove them when idle. The queue then also became a signal: a growing queue tells Jenkins to create more agents, and an empty queue tells it to remove them.
Without queue management
- Builds start all at once and overload machines.
- Heavy jobs starve small ones.
- Nobody knows why a build is waiting.
- Money is wasted on idle machines or time is wasted on waiting.
With good queue management
- Load is spread evenly and safely.
- Important work is not blocked by unimportant work.
- Every waiting item has an explained reason.
- Capacity grows and shrinks with demand.
A bank with one teller uses one line. A bank with ten tellers and different windows for loans, deposits, and foreign currency needs a smarter system that sends each customer to a suitable window. Jenkins went through the same growth, from one line for one teller to many windows with specialised skills.
Real-world motivation
Companies that run large build farms describe the queue as their most important health signal. Teams with hundreds of developers watch queue wait time the way a website team watches page load time, because both directly shape how people feel about the tool.
3Core Concepts: The Words You Must Know
A handful of ideas explain almost everything about queues.
Controller
The central Jenkins server. It owns the queue, decides what runs where, and stores results. Modern practice is to let it coordinate rather than run heavy builds.
Agent
A worker machine or container that runs builds. Agents can be permanent machines or short-lived cloud instances.
Executor
One slot on an agent that can run one build at a time. An agent with four executors can run four builds together.
Label
A tag on an agent, such as “linux” or “gpu.” Jobs ask for a label to say what kind of machine they need.
Quiet period
A short delay before a triggered build enters the ready state, so several quick changes can be combined into one build.
Concurrency limit
A rule that limits how many builds of a job, or a group of jobs, may run at the same time.
Priority
A way to let some queue items go before others, instead of strict first-come, first-served.
Elastic agents
Agents created and removed automatically according to demand, usually in the cloud or on a container platform.
Vocabulary table
| Word | Meaning | Example |
|---|---|---|
| Queue time | How long a build waits before it starts running | Four minutes between push and start |
| Utilisation | The share of capacity that is in use | Nine of ten executors busy is ninety percent |
| Throughput | How many builds finish in a period | Sixty builds per hour |
| Starvation | A job that waits far too long because others always go first | A small job stuck behind endless heavy ones |
| Fan-out | One event that creates many builds at once | A change that triggers fifty downstream jobs |
| Executor slot leak | An executor held by a build that is only waiting, not working | A pipeline that waits for approval on an agent |
Two numbers describe the health of a build system better than any others: how long builds wait in the queue, and how busy the executors are. Watch both, and you will spot most problems early.
4Architecture and Components
Requests flow in from several sources, meet the queue on the controller, and leave for the agents that can run them.
The players
The triggers produce build requests. The controller keeps the queue and runs the scheduler, the part that decides which item goes to which executor. Agents provide executors. A cloud provisioner, when used, watches the queue and creates new agents if the line grows. Monitoring observes queue length, wait times, and utilisation.
flowchart LR
T1["Webhook from code host"] --> Q["Build Queue on Controller"]
T2["Scheduled trigger"] --> Q
T3["User clicks build"] --> Q
T4["Upstream job finishes"] --> Q
Q --> SCH["Scheduler matches items to executors and labels"]
SCH --> A1["Static agents with executors"]
SCH --> A2["Elastic cloud agents"]
Q -->|"Queue length signal"| PROV["Cloud Provisioner"]
PROV --> A2
A1 --> RUN["Builds run"]
A2 --> RUN
Q --> MON["Metrics for queue time and length"]
A1 --> MON
A2 --> MON
Reading the diagram
Requests arrive from webhooks, schedules, people, and upstream jobs, and all of them land in the same queue on the controller. The scheduler looks at each item, checks which agents can run it, and hands it to a free executor. If the queue grows and cloud agents are configured, the provisioner is told to create more of them. Metrics record how long items wait and how busy agents are, giving the team the numbers that guide decisions.
Where the queue lives
The queue is held in the memory of the controller and is saved to disk regularly and at shutdown, in a file in the Jenkins home directory. If the controller restarts, it reads the file and restores the waiting items, so requests are not lost. The controller is therefore the single place where waiting is managed, which is also why an overloaded controller slows the whole system.
Think of an airport check-in hall. Passengers arrive by taxi, train, and bus (triggers). One central desk keeps the list and assigns them to counters (scheduler). Counters are opened or closed depending on the crowd (elastic agents). The airport also counts how long people wait, so that managers can react.
One queue, many rules
Although there is one queue, many rules shape how items leave it: labels, concurrency limits, locks, throttles, priorities, and quiet periods. The rest of this guide explains each rule, so that when an item is stuck, you know which rule to suspect.
5The Life of a Queue Item
A queue item is not simply “waiting.” It passes through several states, and each state has its own reasons and its own fixes.
The states, in plain words
Waiting
The request has just arrived and is sitting in its quiet period, a short delay that lets several quick changes merge into one build.
Blocked
The quiet period is over, but a rule forbids starting now. For example, another build of the same job is running, or a lock is held, or an upstream job is in progress.
Buildable
No rule blocks the item. It is ready and only needs a free executor on a matching agent. Most of the waiting time you see on a busy system is spent here.
Pending
An executor has been chosen, and Jenkins is handing the item over to it. This state is brief, but it can stick if the agent is having trouble.
Left
The item has left the queue, because the build started, or because someone cancelled it.
Why the distinction matters
Blocked and buildable items look alike on the page, because both are “waiting.” But their causes and cures differ completely. A buildable item needs more capacity or better matching. A blocked item needs someone to understand which rule holds it back. Adding more agents will not unblock an item held by a lock.
| State | What holds it | Usual fix |
|---|---|---|
| Waiting | The quiet period | Nothing, or shorten the period for urgent jobs |
| Blocked | A rule, such as no concurrent builds, a lock, or a blocking job | Review the rule, or finish or cancel the blocker |
| Buildable | No free matching executor | Add capacity, fix labels, or reduce demand |
| Pending | Handover to an agent | Check the agent’s health and connection |
At a restaurant, a party may wait because the host is still writing its name (waiting), because the table they want is being cleaned (blocked), because all tables are full (buildable), or because the waiter is carrying menus over (pending). Each cause needs a different response.
When someone says “my build is stuck in the queue,” the first question should be: “What does the queue say is the reason?” Jenkins shows a sentence next to every item, and it usually contains the answer.
6Data Flow and Lifecycle of a Build Request
Follow one build from the moment code is pushed to the moment an executor starts it, including the case where a new cloud agent must be created first.
sequenceDiagram
participant D as Developer
participant H as Code Host
participant Q as Build Queue
participant S as Scheduler
participant P as Cloud Provisioner
participant A as Agent Executor
D->>H: Push commit
H->>Q: Webhook creates queue item
Q->>Q: Wait out the quiet period and merge repeats
Q->>S: Item becomes buildable
S->>S: Look for free executor with matching label
S->>P: No free agent so signal demand
P->>A: Start new agent
A-->>S: Agent connects and offers executor
S->>A: Assign the build
Q-->>Q: Item leaves the queue
A->>A: Run the build
A-->>D: Result reported on the commit
The lifecycle in plain steps
Request
A push, a click, or a timer creates a queue item. The item records the job, the parameters, and the cause.
Quiet period
The item waits a few seconds. Repeated requests for the same job with the same parameters merge into the same item.
Rules check
Jenkins checks concurrency limits, locks, and blocking rules. If any rule says stop, the item is blocked.
Matching
The scheduler looks for a free executor on an agent whose labels satisfy the job’s request.
Provisioning, if needed
If no agent is free and cloud agents are configured, Jenkins asks the provisioner to start one. This can take seconds or minutes.
Assignment
The item is handed to an executor and leaves the queue. The build begins.
Completion
The executor is freed and immediately available to the next matching item.
Where the time goes
Total wait is the sum of several small waits: the quiet period, any blocked time, the search for a free executor, and the provisioning of a new agent. Reducing wait time starts with knowing which of these dominates. A team that shortens the quiet period to zero but ignores a five-minute agent start-up has fixed the wrong thing.
Measure each stage separately if you can: time in the quiet period, time blocked, time buildable, and time to provision. A breakdown turns “the queue is slow” into a specific, fixable problem.
Taking a taxi involves several waits: booking the ride, waiting for a driver to accept, waiting for the driver to arrive, and waiting for the light to change. Complaints about “a slow taxi” only become useful when you know which of those waits was long.
7Executors and Nodes: Where Capacity Comes From
The queue drains only as fast as executors free up. Understanding executors is the key to understanding capacity.
What is an executor?
An executor is a slot on a machine that can run one build at a time. A machine with four executors can run four builds together. Jenkins uses the word node for any machine that provides executors, including the controller itself, which is called the built-in node in current versions.
The controller should not build
Current guidance is to set the number of executors on the built-in node to zero. The controller has an important job: it keeps the queue, serves web pages, stores results, and talks to agents. Heavy builds on the same machine compete with that work and can slow everyone. There is a security reason too. Build code running on the controller can reach its files and secrets.
How many executors per agent?
There is no universal number, but a helpful rule of thumb is to match the executors to what the builds need:
| Kind of build | Suggested executors | Reason |
|---|---|---|
| Processor-heavy, such as compiling | About one per processor core | More executors only make each build slower |
| Memory-heavy, such as large test suites | Enough that memory is not exhausted | Running out of memory kills builds |
| Waiting-heavy, such as calling slow services | More than the number of cores | Builds spend time idle, so machines can host more |
| Container-based agents | One executor per container | Isolation is provided by the container itself |
Many small agents or few large ones?
Many small agents
- Better isolation between builds.
- Easier to scale up and down.
- A failure affects fewer builds.
Costs of many small agents
- Each needs tools and caches prepared.
- More start-up overhead.
- More machines to manage.
Few large agents
- Shared caches and tools are efficient.
- Fewer machines to manage.
- Good for heavy, parallel builds.
Costs of few large agents
- Builds interfere with one another.
- A failure kills many builds at once.
- Harder to scale smoothly.
A kitchen with too many cooks in a small space slows everyone down, because they get in each other’s way. A kitchen with too few cooks lets orders pile up. The number of executors per machine is the number of cooks per kitchen: it should match the space and the size of the meals.
Do not raise executor counts simply to make the queue shorter. If the machine’s processors or memory are already saturated, more executors make every build slower, and total throughput may even fall.
8Labels: Sending Work to the Right Machines
Not every build can run on every agent. Labels are how jobs say what they need and agents say what they offer.
What a label is
A label is a short tag attached to an agent. Typical labels describe the operating system, the installed tools, the hardware, or the purpose: “linux,” “windows,” “docker,” “gpu,” “large,” or “release.” A job or a pipeline stage asks for a label, and Jenkins runs it only on agents that carry it.
Label expressions
Jobs can ask for more than one label using simple logic. A job may need “linux and docker,” or “windows or mac,” or “not slow.” The expression describes the set of acceptable agents. The richer the expression, the smaller the pool that can run the job, and the greater the chance that the item waits.
Pools as a queue design tool
General pool
Many identical agents for everyday builds. Any item that asks for the general label can use any of them.
Special hardware pool
A few expensive agents, such as those with graphics cards or large memory, reserved for jobs that truly need them.
Release pool
Agents kept clean and protected for deployments, so a flood of test builds cannot delay a release.
Team pool
Agents dedicated to one team, so a busy team cannot starve the others, and each team feels responsible for its own capacity.
The matching trap
Labels create a subtle problem: a big pool of idle agents does not help an item whose label matches none of them. An item waiting for the label “gpu” will wait even if fifty general agents are idle. The queue message says so, for example “waiting for next available executor on gpu.” When you see long waits with idle capacity elsewhere, check labels first.
| Situation | What the queue shows | What to do |
|---|---|---|
| Label exists, all its agents busy | Waiting for the next available executor on that label | Add agents to that pool, or reduce demand |
| Label exists, all its agents offline | All nodes of that label are offline | Bring agents back, or check the cloud provisioner |
| Label matches no agent | There are no nodes with that label | Fix the label spelling, or create the agents |
A hospital has a general ward, an intensive care unit, and a children’s ward. A child who needs a bed does not use an empty adult bed. The system is efficient only if each ward has the right number of beds for its patients. Labels are the ward signs.
Keep the label vocabulary small and documented. Twenty-five ad hoc labels create twenty-five tiny pools, each with its own queue, and most of them are either idle or overloaded.
9Quiet Periods, Merging, and Duplicate Requests
Jenkins deliberately delays and combines requests to avoid doing the same work twice.
The quiet period
When a build is requested by a trigger such as a code push, Jenkins does not start it at once. It waits for a short time, five seconds by default, called the quiet period. If another request for the same job arrives during that time, Jenkins folds it into the same queue item. The result is one build that sees all the changes, instead of several builds racing each other.
Merging of identical requests
If a job is already in the queue and another request arrives with the same parameters, Jenkins usually does not add a second item. It notes the extra cause on the existing item. This protects the queue from being flooded by repeated clicks or repeated triggers. If the requests carry different parameter values, they are different requests, and each one gets its own item.
Choosing the quiet period
| Situation | Quiet period choice |
|---|---|
| Developers push several commits in a row | A longer period, such as thirty to sixty seconds, combines them |
| Urgent hotfix jobs | A very short or zero period for the fastest start |
| Jobs triggered by many upstream events | A moderate period, to absorb bursts |
| Manually started builds | Usually no need to delay |
The trade-off
A longer quiet period saves capacity, because fewer builds run, but it delays feedback by that many seconds. A shorter period gives faster feedback but may run more builds. For busy repositories, a moderate delay often produces both less load and a better overall experience.
Parameters and duplicates
Parameterised builds deserve special care. If a form has a field that changes on every request, such as a timestamp, no two requests are ever identical, and merging never happens. A few automated callers can then flood the queue with near-identical items. Keep parameters meaningful, and avoid adding values that change every time for no reason.
When several colleagues each tell a receptionist to “book the meeting room,” a good receptionist waits a moment, notices that all the requests are the same, and books it once. Merging requests saves effort and avoids double bookings.
Do not set the quiet period so long that developers begin to think Jenkins is ignoring them. If people wait a minute before anything visible happens, they will start clicking the build button, which creates more requests.
10Why Is My Build Waiting? Reading the Queue Reasons
Jenkins tells you why each item waits. Learning to read the messages solves most mysteries in seconds.
The common messages
| Message in the queue | Meaning | First response |
|---|---|---|
| In the quiet period | The delay before the build becomes ready | Wait a few seconds |
| Waiting for next available executor | All executors are busy | Check capacity and demand |
| Waiting for next available executor on a label | All executors of that label are busy | Check that pool |
| All nodes of a label are offline | Matching agents exist but are disconnected | Reconnect agents or check the provisioner |
| There are no nodes with a label | No agent has that label | Fix the label or create agents |
| A build of the job is already in progress | Concurrent builds are not allowed for that job | Wait, or allow concurrency if safe |
| Blocked by another job or resource | A blocking rule or lock is active | Find what holds it |
| Upstream or downstream project is building | The job waits for related jobs | Review the dependency setting |
A step-by-step investigation
Read the message
Hover over or open the queue item, and read the reason exactly.
Blocked or buildable?
Decide whether a rule holds the item or only capacity does.
Check the label
Confirm which agents carry the requested label and whether any are free.
Look at the executors
Open the node list. See which builds occupy executors, and how long they have run.
Look for stuck builds
A build waiting for an approval, or hung on a network call, may hold an executor for hours.
Decide and act
Free the executor, add capacity, fix the label, or change the rule.
When the message is silent
Occasionally an item shows no clear reason, or stays in the handover state for a long time. This often points to trouble with an agent, such as a broken connection or a full disk. Check the agent’s status page and log, and consider disconnecting and reconnecting it.
A train departure board says “delayed: signal failure” or “delayed: waiting for crew.” The reason matters, because it tells passengers whether to wait, to walk, or to find another route. The queue’s reason line does the same for builds.
Teach every developer to read the queue reason before asking for help. Most questions to the platform team disappear once people know that “there are no nodes with label x” means a typo, not an outage.
11Queueing Theory for Humans: Why Waits Explode
A simple idea from mathematics explains why queues seem fine for months and then suddenly become terrible.
The surprising shape of waiting
Imagine ten executors and builds that each take ten minutes. The system can finish sixty builds per hour if it is perfectly busy. If requests arrive at thirty per hour, executors are about half busy, and builds start almost at once. At fifty per hour, executors are busy most of the time, and waits are noticeable. At fifty-eight per hour, waits are long. At sixty or above, the queue grows without limit, because work arrives faster than it can be done.
| Requests per hour | How busy the executors are | Typical experience |
|---|---|---|
| 30 | About half | Builds start almost immediately |
| 45 | About three quarters | Short, occasional waits |
| 54 | About ninety percent | Waits of several minutes at busy moments |
| 58 | Almost full | Long waits, sudden spikes |
| 60 or more | Full | The queue grows without end |
The lesson: do not aim for full utilisation
Waiting time does not rise in a straight line as the system fills up. It stays low for a long time, and then it rises steeply as the system approaches full use. A system running at ninety-five percent looks efficient on a chart, but its users experience long waits. Many teams aim for utilisation of around sixty to seventy percent at peak, leaving room for bursts.
Bursts matter more than averages
Averages hide the real trouble. If most builds arrive in the two hours after lunch, or right at the start of the working day, the system must handle those peaks, not the daily average. A system that is quiet all night and overloaded from nine to eleven has a peak problem, whatever the average says.
Long jobs hurt everybody
A single build that takes three hours blocks an executor for the whole time. A handful of such jobs can occupy a large part of a small pool. Mixing quick jobs and long jobs in one pool is one of the most common causes of slow queues. Separate pools for long jobs, or limits on how many may run at once, protect the quick ones.
Leave headroom
Plan for peaks, not averages, and keep some capacity spare.
Watch the steep part
When utilisation passes about eighty percent at peak, waits start rising quickly.
Separate long from short
Do not let three-hour jobs block one-minute jobs.
Shorten builds
Cutting build time raises capacity as surely as adding machines.
A motorway carries traffic smoothly until it is nearly full, and then one small braking event causes a jam that lasts an hour. Roads that run close to capacity are fragile. Build systems behave the same way, so a little spare room makes the whole system calmer.
Speeding up builds is often cheaper than buying capacity. A build that takes ten minutes instead of twenty doubles what the same executors can do, and it also shortens the feedback loop for developers.
12Concurrency Control: Limiting Overlap
Sometimes the goal is to make builds wait on purpose, so that they do not trample each other or the systems they touch.
Why limit overlap?
Two builds of the same job that run at the same time can interfere. They may write to the same test database, deploy to the same environment, or fight over the same files. Limiting how many run together protects shared resources, even though it lengthens the queue.
The options in Jenkins
Do not allow concurrent builds
A setting on the job that lets only one build of it run at a time. Others wait in the queue, blocked, until the running one finishes.
Disable concurrent builds option
The same idea written in the Jenkinsfile. Newer versions can also abort the older build when a new one arrives, keeping only the latest.
Milestone
A marker in a pipeline. When a newer build passes a milestone, older builds that have not yet reached it are cancelled, so only the newest proceeds.
Lock
A step from the Lockable Resources plugin that lets only one build hold a named resource, such as a test environment, at a time. Others wait for their turn.
Waiting versus cancelling
Make old builds wait
- Every build gets its result.
- Good for deployments that must happen in order.
- Queue can grow if builds are slow.
Cancel old builds
- Saves capacity when only the latest matters.
- Good for pull request builds and branch builds.
- Older results are never produced.
Which fits which job
| Kind of job | Best rule |
|---|---|
| Pull request and branch checks | Cancel superseded builds, keep the newest |
| Deployments to one environment | One at a time, in order, with a lock |
| Nightly full test suite | No concurrent runs, so it cannot overlap itself |
| Independent utility jobs | Allow concurrency, no special rule |
Two painters cannot paint the same wall at the same time, so the second waits for the first. But if a customer changes the colour, there is no reason to finish the old colour. Locks are for the painters who must wait, and milestones are for the colours that no longer matter.
For any job triggered by every push, ask: “If a newer build starts, does anyone still want the older result?” If the answer is no, cancel the old one. This single habit often halves the load on a busy system.
13Throttling, Blocking, and Locks
Several plugins give finer control than the built-in settings. Use them with care, because every rule is another reason for an item to wait.
Throttle Concurrent Builds
The Throttle Concurrent Builds plugin limits how many builds may run at once, either for one job or for a named group of jobs called a category. It can also limit how many builds of a category may run on a single node. It is ideal for protecting a limited outside resource, for example “no more than three builds may use the shared test database at once,” or “no more than two heavy jobs per agent.”
Build Blocker
The Build Blocker plugin lets a job refuse to start while certain other jobs are running, chosen by name patterns. Use it when two jobs conflict but do not share a named resource, for example a backup job that must not overlap with a big deployment.
Lockable Resources
The Lockable Resources plugin lets you declare named resources and ask for them in a pipeline. A build holds the lock while its block runs, and others queue for it. Locks can also pick one resource from a labelled group, so several identical test environments can be shared fairly among builds.
Choosing the right tool
| Need | Best tool |
|---|---|
| A limit on total parallel runs of a group of jobs | Throttle Concurrent Builds |
| Exclusive use of a named resource, such as an environment | Lockable Resources |
| Two specific jobs must never overlap | Build Blocker, or a shared lock |
| Only one run of one job at a time | The built-in no-concurrent-builds setting |
The hidden cost
Locks and throttles hold executors in some designs. A pipeline that takes an agent first and then waits for a lock keeps that agent idle while it waits. If many builds do this, they can fill the pool with builds that are only waiting, and starve the builds that could have run. Whenever possible, acquire locks before taking an agent, so that waiting costs nothing.
Benefits of throttles and locks
- Protect fragile shared resources.
- Prevent hard-to-debug collisions.
- Make the order of work predictable.
Risks
- Items can wait for reasons nobody remembers.
- Waiting builds may hold executors.
- A forgotten lock can block a whole team.
- Rules pile up and interact in confusing ways.
Document every throttle and lock: what it protects, who owns it, and where it is used. An undocumented lock is a future mystery at three in the morning.
A meeting room booking system prevents two teams from using the same room. It works well, until someone books the room for a whole day and never turns up. Locks need the same discipline: timeouts, owners, and a way to release them.
14Priorities and Fairness
By default, the queue is roughly first come, first served. Sometimes that is not what a company wants.
The default order
Without extra rules, items are taken in the order they became ready, subject to label matching. That is simple and fair in the sense of arrival time, but it treats a one-minute check and a three-hour test suite alike, and it treats a production hotfix like a routine nightly build.
Priority plugins
Plugins such as Priority Sorter let administrators give jobs numeric priorities, often by folder, view, or job name pattern. Higher-priority items are taken first when executors free up. Common uses are letting release and hotfix jobs jump ahead of routine builds, and letting quick feedback jobs go before long ones. Check the plugin’s current maintenance status before adopting it.
The risk of priorities
Priorities can cause starvation. If high-priority jobs keep arriving, low-priority jobs may never start. A team that marks everything “high priority” achieves nothing, because the top level becomes the new ordinary. Use few levels, and reserve the top for the truly urgent.
Fairness between teams
Priorities decide the order of items, but they do not divide capacity fairly. If one team runs a huge test matrix, it can fill the pool while the others wait. The usual answers are:
- Separate pools with their own labels, so each team has guaranteed capacity.
- Throttle categories so no team can use more than a share of the pool.
- Chargeback or visibility, where each team sees its own usage and cost, which gently encourages efficient use.
| Approach | Strength | Weakness |
|---|---|---|
| Strict arrival order | Simple and predictable | Urgent work waits behind routine work |
| Priorities | Urgent work goes first | Starvation and priority inflation |
| Separate pools per team | Guaranteed capacity, clear ownership | Idle capacity in one pool cannot help another |
| Throttles per team | Cap on any one team’s share | More rules to manage |
A fast lane at a supermarket helps shoppers with few items, but if everyone claims to have few items, the fast lane clogs. Priorities need honest use and a simple rule about who qualifies.
Start with separate pools and simple concurrency rules. Add priorities only when a clear, recurring problem justifies them, and keep the number of levels small.
15Pipeline Design That Respects the Queue
How you write a pipeline decides how many executors it occupies and for how long. Careless pipelines waste capacity quietly.
Do not hold an executor while waiting
A pipeline can pause for human approval with the input step, wait for a condition with waitUntil, or sleep. If these steps run inside an agent block, the executor is held the whole time, doing nothing. A build that waits overnight for a manager’s approval occupies an executor overnight. Pipelines have a special ability: steps outside any agent block run on a lightweight slot on the controller, which does not consume a normal executor. So the advice is: take an agent only for the steps that need one, and put waiting steps outside it.
Use an agent per stage
In Declarative Pipeline, setting the top-level agent to none and choosing agents per stage means each stage takes and releases an executor as needed. The approval stage runs with no agent, and the build stages take one only when they run.
Beware of nested agent blocks
If a pipeline takes an executor and, inside it, asks for another agent block, it holds the first while waiting for the second. If many pipelines do this at the same time, and the pool is small, every executor may be held by a build that is waiting for another executor. Nobody can proceed. This is a classic deadlock.
flowchart TD
A["Pipeline takes executor 1"] --> B["Inside it asks for a second agent block"]
B --> C{"Is a second executor free"}
C -->|"Yes"| D["Runs and finishes, releases both"]
C -->|"No, pool full of similar pipelines"| E["Waits while holding executor 1"]
E --> F["Every executor is held by a waiting pipeline"]
F --> G["Deadlock and queue grows forever"]
Parallel branches and fan-out
The parallel step starts several branches at once. If each branch asks for its own agent, a single pipeline may demand many executors at the same moment. Twenty parallel branches from one build can occupy a small pool completely. Limit the number of parallel branches, use failFast to stop the rest when one fails, and consider throttle categories so that one pipeline cannot take over.
Right-size each stage
Stages that only send a message or check a small condition do not need a heavy agent. Ask for the lightest label that will do the job. This keeps expensive agents free for work that truly needs them.
| Habit | Effect on the queue |
|---|---|
| Approval or waiting inside an agent block | Executors sit idle and the queue grows |
| Agent per stage, none at the top | Executors are held only while working |
| Nested agent blocks | Risk of deadlock in busy pools |
| Unlimited parallel branches | One build can flood the pool |
| Lightest label per stage | Scarce agents stay available |
A person who reserves a lab bench and then goes to lunch, while waiting for a signature, keeps the bench unused for an hour. A considerate colleague hands the bench back, gets the signature, and reserves it again. Good pipelines behave like the considerate colleague.
The slowest queue problems are often invisible in the queue itself. The line looks long, while many executors sit occupied by builds that are merely waiting. Look at what the busy executors are actually doing before you buy more of them.
16What Fills the Queue: Triggers and Bursts
Half of queue management is controlling what goes into the queue in the first place.
Polling versus webhooks
Jenkins can learn about code changes by polling, which means asking the repository at intervals whether anything changed, or through webhooks, which are messages sent by the repository the moment something happens. Polling many repositories every minute creates load and delays. Webhooks are faster and cheaper, with polling kept only as a backup.
Scheduled builds and the thundering herd
Schedules that all say “midnight” start every job at exactly the same moment, creating a wall of demand. Jenkins schedules support a special symbol, written as the letter H, which spreads start times by a hash of the job name. Using it turns one big spike into a gentle spread across the hour.
Downstream fan-out
A job that triggers many downstream jobs when it finishes creates a burst of items at once. Ten upstream jobs each triggering ten downstream jobs generate a hundred items in minutes. Control this with throttle categories, with sensible dependency design, and with quiet periods that merge repeated triggers.
Multibranch scans and pull requests
Multibranch pipelines scan repositories and create jobs for branches and pull requests. A new repository with many branches, or a large rebase, can create dozens of builds at once. Filter which branches are built, cancel superseded builds, and avoid building stale branches automatically.
Automation that hammers the queue
Scripts and tools that call Jenkins can create builds in loops. A misbehaving script can fill the queue with thousands of items. Use API tokens per tool, so you can tell who is responsible, and consider rate limits at a proxy in front of Jenkins.
Use webhooks
Faster and lighter than polling many repositories.
Use the hash symbol in schedules
Avoid all jobs starting at the same minute.
Quiet periods
Combine bursts of commits into single builds.
Supersede old builds
Do not run builds nobody wants any more.
Build only what matters
Skip stale branches and documentation-only changes where safe.
Per-tool tokens
Know which script created which requests.
Cinemas do not start every film at exactly eight o’clock, because the car park and the ticket desk would overflow. Staggering start times spreads the crowd. The hash symbol in a schedule is the cinema manager staggering the films.
Look at a chart of queue arrivals by hour and by source. You will often find one trigger, one script, or one schedule that accounts for a startling share of the load.
17Elastic Agents: Letting the Queue Drive Capacity
Instead of guessing how many agents you need, let demand create them, and let idleness remove them.
How it works
Cloud and container plugins teach Jenkins to create agents on demand. When items wait in the queue with a label that a cloud can provide, Jenkins asks the cloud to start an agent. When the agent has been idle for a set time, Jenkins removes it. The queue is both the signal and the customer.
Common platforms
| Platform | How agents appear | Typical controls |
|---|---|---|
| Kubernetes | Each build gets a fresh pod from a template | Pod templates, container caps, idle retention |
| Cloud virtual machines | Machines are started from images | Instance caps, idle termination, image choices |
| Container hosts | Containers are started on a pool of hosts | Host limits, image caches |
The settings that matter
- Maximum agents: a hard cap that protects your budget and your cloud quota. Without it, a burst or a bug can create hundreds of machines.
- Idle time before removal: too short, and you pay start-up delays again and again. Too long, and you pay for idle machines.
- Start-up time: the time from demand to a ready agent. Prepared images with tools installed start faster than machines that install everything at boot.
- Warm capacity: a small number of agents kept ready all the time, so common builds start immediately.
- Templates per label: each label maps to a template that describes size, tools, and limits.
Strengths and limits
Strengths
- Capacity follows demand automatically.
- Clean agents for every build.
- You pay mainly for what you use.
- Peaks are handled without permanent machines.
Limits
- Start-up delay for each new agent.
- Cloud quotas and rate limits can throttle growth.
- Cold caches make builds slower.
- Costs can surprise you without caps.
A ride-hailing company sends more drivers into busy areas and lets them go home when it is quiet. Riders wait a few minutes when demand spikes suddenly, because drivers take time to arrive. Elastic agents behave the same way, with the same trade of cost against waiting.
Always set a maximum on elastic agents. A stuck loop, a fork bomb of triggered jobs, or a runaway script can otherwise create expensive machines faster than anyone can notice.
18Choosing a Strategy: A Decision Guide
When queue times are too long, the cause could be capacity, matching, rules, or wasteful builds. A short guide points to the right fix.
flowchart TD
S["Queue time is too long"] --> Q1{"Are items blocked or buildable"}
Q1 -->|"Blocked"| B1["Find the rule, lock or throttle holding them"]
Q1 -->|"Buildable"| Q2{"Is there idle capacity with other labels"}
Q2 -->|"Yes"| M["Fix labels or rebalance pools"]
Q2 -->|"No"| Q3{"Are executors doing useful work"}
Q3 -->|"No, waiting or hung"| W["Move waits outside agents and add timeouts"]
Q3 -->|"Yes"| Q4{"Is demand wasteful"}
Q4 -->|"Yes, superseded or duplicate builds"| C["Cancel old builds and merge requests"]
Q4 -->|"No"| Q5{"Can builds be made faster"}
Q5 -->|"Yes"| F["Cache, parallelise, trim tests"]
Q5 -->|"No"| A["Add capacity or elastic agents"]
Why this order
The path goes from the cheapest and most likely explanation to the most expensive. Rules and labels cost nothing to fix. Wasteful demand is usually cheaper to remove than to serve. Speeding up builds raises capacity without buying machines. Adding capacity comes last, because it treats the symptom and can hide the real cause.
Examples of the path in action
| Observation | Likely cause | Fix |
|---|---|---|
| Long waits, many idle agents in another pool | Label mismatch | Rebalance pools or widen labels |
| Executors busy but CPU idle | Builds waiting for approvals or slow services | Move waits outside agents, add timeouts |
| Several builds of the same branch queued | Superseded builds | Cancel older ones automatically |
| Wait spikes at nine each morning | Peak demand | Elastic agents or warm capacity |
| Items waiting on a lock for an hour | Long or forgotten lock holder | Add lock timeouts and owners |
Before a shop hires more staff because the queue is long, a sensible manager checks whether the till is broken, whether a queue for the wrong counter has formed, and whether staff are chatting instead of serving. Only then does it make sense to hire.
Write this decision path on a page in your team’s documentation and follow it every time someone reports a slow queue. A repeatable diagnosis beats a different guess every time.
19Security: Who Can Fill, Cancel, and Abuse the Queue
The queue is a shared resource, and shared resources attract accidents and abuse.
Permissions
Jenkins has fine-grained permissions. The right to start a build, the right to cancel a build or a queue item, and the right to configure jobs are separate. A sensible setup gives most developers the right to build and cancel their own team’s jobs, keeps configuration rights narrower, and reserves administrator rights for a small group. Otherwise anyone might cancel another team’s release build, or reconfigure a job that all others depend on.
The queue as a target
Flooding the queue with expensive items is a simple way to cause trouble, whether by a careless script or by malice. Every item costs memory on the controller, and every started build costs agent time, and money if the agents are elastic. Attackers can also use builds to run their own code on your machines, for example to mine cryptocurrency.
Defences
Limit who can build
Require login. Give the build permission only to people and tools that need it.
Per-tool API tokens
Every script and integration uses its own token, so its requests can be traced and revoked.
Rate limits at the proxy
A reverse proxy in front of Jenkins can limit request rates from any one client.
Hard caps on elastic agents
A maximum number of cloud agents limits the cost of any flood.
Careful with untrusted code
Pull requests from outsiders run their code on your agents. Use strict trust policies and isolated agents.
Build time limits
A maximum duration prevents runaway builds from holding executors for days.
Separate the sensitive pools
Release and deployment builds hold powerful credentials. Give them their own agents, with their own labels, so that ordinary or untrusted builds can never run on the same machines. Then a flood of pull request builds can neither delay a release nor reach its secrets.
Cancelling and visibility
Cancelling is a power. Log who cancels what. A queue item that vanishes, or a build that is aborted, should leave a trail. Audit logs help resolve arguments between teams and help spot suspicious activity.
Safer habits
- Named permissions and per-tool tokens.
- Separate pools for sensitive work.
- Caps and time limits everywhere.
- Audit of who builds and cancels.
Risky habits
- Anonymous users allowed to build.
- One shared token for every script.
- Releases and pull requests on the same agents.
- Unlimited elastic agents and no build timeouts.
A public phone line to the emergency service is a shared resource. If anyone could tie it up with false calls, real emergencies would suffer. Access control, tracing, and limits keep the line usable for the people who need it.
20Performance and Capacity Planning
Capacity planning turns guessing into arithmetic. You do not need complex tools to do it well.
The basic calculation
Capacity in builds per hour is roughly the number of executors multiplied by sixty, divided by the average build time in minutes. Ten executors and ten-minute builds give sixty builds per hour. Demand is the number of build requests per hour at peak. If demand approaches capacity, waits explode, as we saw in the theory chapter.
A simple planning routine
Measure demand at peak
Count queue arrivals per hour during the busiest hours, by label and by team.
Measure service time
Find the average and the long tail of build durations. The tail matters, because long builds hold executors.
Compute capacity
Multiply executors by the builds each can finish per hour.
Add headroom
Aim for peak utilisation of about sixty to seventy percent.
Plan for growth
Ask teams about new projects and hiring. Demand often grows faster than people expect.
Check the whole chain
Agents are not the only limit. The controller, the network, the artifact store, and the source server may also become bottlenecks.
Levers that raise capacity
| Lever | Effect | Cost |
|---|---|---|
| Shorter builds through caching and parallel tests | More builds per executor | Engineering time |
| More executors on existing machines | More parallelism, if resources allow | Low, but limited by hardware |
| More agents | Linear growth in capacity | Machine cost |
| Elastic agents | Capacity follows demand | Start-up delay and cloud spend |
| Cancel wasted builds | Frees capacity without buying any | Low |
| Split pools by job length | Quick jobs stop waiting behind long ones | Some idle capacity per pool |
The controller is a bottleneck too
A controller with too many jobs, too many agents, or too many plugins can slow down scheduling itself. Symptoms include a sluggish web page, and a queue that fills even though executors are free. When that happens, consider splitting into several controllers, each with its own set of teams and agents. This limits the blast radius and spreads the scheduling work.
Do not forget the outside systems
More executors mean more simultaneous downloads and uploads. The package registry, the code host, and the artifact store all have limits. If builds run faster than those systems can serve them, the queue moves to another place, and failures start showing up as timeouts.
Adding more checkout counters helps only if the shop has enough shelves stocked and enough doors for customers. Capacity planning looks at the whole shop, not just the tills.
Keep a simple one-page capacity sheet: peak demand, average and long-tail build times, executors, expected growth, and the planned action date. Review it every quarter.
21High Availability and Reliability
The queue must survive restarts, lost agents, and busy days, or teams will lose work and trust.
What happens on a restart
The controller saves the queue to disk in its home directory and restores it at start-up. Items that were waiting return to the queue. Builds that were running are handled according to the type of job and the durability settings: many pipelines can resume, while others must be restarted. Plan restarts for quiet times, and use the quiet-down feature before maintenance so running builds can finish first.
What happens when an agent disappears
If an agent is lost while running a build, that build fails or, for suitable pipelines, can be retried on another agent. Elastic agents are removed by the platform from time to time, for example by reclaiming a cheaper machine, so pipelines should expect and survive agent loss for infrastructure reasons.
Failure modes to plan for
| Failure | Effect on the queue | Defence |
|---|---|---|
| Controller restart | Queue reloaded from disk, running builds may resume or restart | Restart in quiet hours, back up the home directory |
| Agent crash | Builds on it fail, items may return to the queue | Retry for infrastructure failures, health checks |
| Cloud quota reached | New agents cannot start, queue grows | Monitor quotas, request increases early |
| Label with no agents | Items wait forever | Alert on items waiting beyond a limit |
| Cloud API outage | Provisioning fails | Keep a few permanent agents as a fallback |
| Overloaded controller | Slow scheduling, delayed starts | Trim plugins and jobs, split controllers |
A safety net of permanent agents
Even a mostly elastic setup benefits from a small number of always-on agents. They serve urgent builds while cloud agents warm up, and they keep the system running if the cloud provider has a problem. It costs a little, and it buys calm.
Stuck items
Items that wait for an impossible reason, such as a label that no longer exists, can sit in the queue for weeks and confuse everyone. Set an alert for items older than a limit, and clean up such items on a schedule.
If your only agents are elastic and the cloud is having a bad day, your whole build system is down. Decide in advance which builds are critical enough to keep a fallback for.
A restaurant that depends on a single delivery van for its ingredients should keep a small store cupboard for the day the van breaks down. A few permanent agents are the store cupboard of a build system.
22Monitoring, Logging, and Metrics
You cannot manage a queue you cannot see. A few well-chosen numbers reveal almost everything.
The essential metrics
More measures worth tracking
- Blocked versus buildable items, which shows whether rules or capacity are the cause.
- Time to provision an agent, from demand to a connected executor.
- Agents online and offline, by pool.
- Long-running builds, those that exceed a sensible duration.
- Executor idle time, to spot wasted, expensive machines.
- Cancelled and superseded builds, to see how much work is being avoided.
- Retries and failures caused by infrastructure, which hint at agent trouble.
Where the numbers come from
Jenkins exposes queue and executor information through its web interface and its programmatic interfaces. Monitoring plugins can publish the numbers to popular monitoring systems, where they can be charted and alerted on. Metric names vary by plugin and version, so check the documentation of the one you install. Even a simple scheduled script that records the queue length every minute gives you a history to learn from.
Alerts that help
| Signal | What it may mean | Action |
|---|---|---|
| Queue time above target for ten minutes | Demand exceeds capacity or a pool is empty | Follow the decision guide |
| An item older than an hour | Stuck on a label, a lock, or a rule | Read its reason and fix it |
| Utilisation above eighty percent at peak | Waits will rise soon | Plan more capacity |
| Agents offline for long periods | Connection or cloud problems | Investigate the pool |
| Provisioning time growing | Slow images or cloud limits | Optimise images, check quotas |
Set a target
Agree on a target for queue time, such as “ninety percent of builds start within two minutes.” A target turns arguments about “slow” into measurable facts and gives the team a shared goal.
Publish the queue time chart on a screen or a shared page. When developers can see the wait time, they adopt healthy habits, such as cancelling builds they no longer need.
An airport shows security wait times on a board, and managers open more lanes when the number rises. Nobody needs to guess. A queue dashboard gives your team the same simple, shared truth.
23Testing Queue Behaviour
Queue rules are code in disguise. Test them before a busy day tests them for you.
Why test?
Locks, throttles, priorities, and elastic agent settings interact in surprising ways. A rule that looks harmless can block a whole team, and an elastic setting that looks safe can create a large bill. Testing on purpose reveals these problems while they are cheap.
Kinds of tests
Burst test
Start many trivial jobs at once, for example fifty jobs that only sleep for a minute, and watch how the queue and the agents respond.
Label test
Create a job for each label and confirm that it runs on the right pool, and shows a clear message when the pool is empty.
Lock test
Start two builds that need the same lock and confirm that the second waits, and that the lock is released after failure and timeout.
Cancel test
Push several commits quickly and confirm that superseded builds are cancelled and only the newest completes.
Elastic test
Create a burst and confirm that agents appear up to the cap, no more, and disappear after the idle time.
Restart test
Restart a test controller with items in the queue and confirm that they return and run.
Use a test Jenkins
Do these experiments on a separate test controller with its own small pool, not on production. A test environment built from the same code as production, using configuration as code, makes the tests realistic and repeatable.
Measure and record
For each test, record what you expected and what happened: how long items waited, how many agents appeared, how the messages read. Keep the results with the rules, so the next person understands why a setting was chosen.
Game days
Once or twice a year, hold a rehearsal in which you simulate a bad day: a cloud quota limit, a lost pool, or a flood of builds. Watch how the alerts and the team respond. The rehearsal will expose gaps in alerts and runbooks far more effectively than reading documents.
A theatre tests its fire exits and lighting cues before opening night, with staff pretending to be an audience. Discovering a jammed door with a real crowd inside is a very different experience. Burst tests are the dress rehearsal for your queue.
24Deployment, Cloud, and Configuration as Code
Queue settings are part of your infrastructure. Keep them in code, so they can be reviewed, tested, and rebuilt.
What belongs in code
| Setting | Why keep it in code |
|---|---|
| Executor counts per node | Capacity changes are reviewed and reversible |
| Labels and pool definitions | The map from labels to agents is documented |
| Cloud templates and caps | Budget limits are visible and controlled |
| Quiet period and global defaults | Consistent behaviour across rebuilds |
| Throttle categories and lockable resources | Rules are found in one place |
| Pipeline options in the Jenkinsfile | Concurrency rules live beside the code they protect |
Configuration as Code
The Jenkins Configuration as Code plugin reads a text file describing the controller’s settings, including nodes, clouds, and many plugin options. Together with a repository and reviews, it makes capacity changes as safe as code changes. A change from ten to twelve executors becomes a small, reviewed edit, not a click that nobody remembers.
Shared libraries for standard behaviour
A shared library can offer standard steps that apply queue-friendly habits automatically: cancelling superseded builds, taking an agent only for the necessary block, applying sensible timeouts, and limiting parallelism. Teams then get good behaviour by default, without each writing it again.
Container platforms
On Kubernetes, pod templates define what each label means: image, resources, and limits. The platform’s own autoscaling adds nodes when pods cannot be scheduled, which creates a second queue underneath the Jenkins one. Watch both. A Jenkins queue that looks fine can hide a cluster that is short of capacity, and the reverse.
Cost controls
Maximum agents
A hard limit per template and overall.
Idle timeouts
Remove agents that have done nothing for a set time.
Right-sized templates
Do not give every build the largest machine.
Alerts on spend
Notify people when cloud costs cross a threshold.
Use case: a Monday morning burst
Every Monday at nine, two hundred developers push weekend work. The team’s warm pool of ten agents handles the first wave, while Kubernetes pod templates create up to eighty more within three minutes. Builds start within a couple of minutes, and by eleven the extra pods are gone. The cost of the burst is a few dollars, and nobody notices the queue.
Whenever you change a queue setting by hand in an emergency, write the same change into code within the same day. Otherwise the next rebuild will silently undo your fix.
25Advantages, Disadvantages, and Trade-offs
Active queue management brings real benefits, and every rule has a cost.
Advantages
- Shorter waits and faster feedback for developers.
- Protection of fragile shared resources.
- Better use of expensive machines.
- Predictable behaviour for releases and hotfixes.
- Lower cloud bills through elastic capacity and cancelled waste.
- Clear evidence for capacity decisions.
Disadvantages
- More rules mean more reasons for an item to wait.
- Priorities can cause starvation and arguments.
- Pools can leave idle capacity in the wrong place.
- Elastic agents add start-up delay and cost risk.
- Tuning takes time and regular attention.
- Complex setups are hard to explain to new people.
Balancing choices
| Choice | Simpler and cheaper | Faster and more controlled |
|---|---|---|
| Agent pools | One shared pool | Pools by team, hardware, and criticality |
| Capacity | Fixed machines | Elastic plus warm agents |
| Ordering | First come, first served | Priorities and throttles |
| Waste control | Manual cancelling | Automatic supersede and merge rules |
| Monitoring | Look at the queue page | Dashboards, targets, and alerts |
Balance simplicity and control
Every rule is a promise that someone will remember why it exists. Add rules only in response to measured problems, and remove them when the problem is gone. A small team with a modest pool needs almost none. A company with hundreds of developers needs many, and the discipline to keep them documented.
There is no universal answer. Match the design to your size, your budget, and your patience for complexity.
26Design Patterns and Anti-patterns
A pattern is a solution many teams discovered independently. An anti-pattern is a trap many teams fell into.
Patterns worth copying
Controller with zero executors
The controller schedules and serves. Agents build.
Pools by workload
Separate pools for quick checks, long jobs, special hardware, and releases.
Supersede and cancel
Newer builds cancel older builds of the same branch or pull request.
Wait outside agents
Approvals and waits run with no agent held.
Warm plus elastic
A few always-on agents for instant starts, with elastic agents for peaks, both capped.
Queue-time target
A published goal, a chart, and an alert.
Anti-patterns to avoid
Builds on the Controller
Running heavy builds on the controller itself, so builds compete with scheduling and the web interface, and build code can reach controller files.
Better approach
Set the controller’s executors to zero and use agents for all builds.
The Agent That Waits
A pipeline that holds an executor while it waits for approval, for a slow service, or for another lock.
Better approach
Take an agent only when work is ready, and place waits outside agent blocks.
Everything Is Urgent
Setting every job to top priority, so that priority no longer means anything and low-priority work starves.
Better approach
Use a few levels, reserve the top for real emergencies, and prefer separate pools.
The Midnight Stampede
Dozens of scheduled jobs all set to start at exactly the same minute, followed by a queue that clears only at dawn.
Better approach
Use the hash symbol to spread start times and separate heavy jobs by design.
Uncapped Elasticity
Cloud agents with no maximum, so a runaway loop or a flood of builds can create hundreds of expensive machines.
Better approach
Set maximums and cost alerts, and keep a few permanent agents as a fallback.
Add Machines First
Buying more capacity as the first reaction to every complaint, without checking labels, locks, waste, and build speed.
Better approach
Follow the decision guide, and add capacity only when the cheaper causes are ruled out.
27Best Practices and Common Mistakes
These lessons are usually learned the hard way. You can learn them the easy way.
Best practices
- Keep the controller free of builds, with zero executors on it.
- Read the queue reason first whenever a build waits.
- Design pools by workload, and keep the label vocabulary small and documented.
- Leave headroom: plan for peaks, and aim for about sixty to seventy percent utilisation at peak.
- Cancel superseded builds and merge repeated requests.
- Do not hold agents while waiting for approvals or slow steps.
- Use webhooks, and spread schedules with the hash symbol.
- Cap everything: parallel branches, elastic agents, build durations.
- Protect sensitive pools from untrusted and routine builds.
- Measure queue time, set a target, and alert on stuck items.
- Keep queue settings in code and test them with bursts.
- Speed up builds before you buy machines.
Common mistakes and their fixes
| Mistake | What happens | Fix |
|---|---|---|
| Typo in a label | Item waits forever with “no nodes with label” | Read the reason, fix the label, alert on old items |
| More executors than the machine can handle | All builds slow down, some fail | Match executors to cores and memory |
| Approval step inside an agent block | Executors idle overnight | Move the approval outside any agent |
| Nested agent blocks | Deadlock when the pool is busy | Take one agent at a time, or reorganise stages |
| Everything scheduled at midnight | Giant spike, long queue | Use the hash symbol to stagger |
| Forgotten lock | A whole team blocked | Add timeouts, owners, and documentation |
| Unlimited parallel branches | One build floods the pool | Limit branches, throttle categories |
| No maximum on cloud agents | Surprise bill | Set caps and spending alerts |
| Ignoring the tail of long builds | Long jobs starve quick ones | Separate pools by job length |
The queue looks long, executors look busy, and the response is to add machines. Later someone discovers that half the busy executors were held by builds waiting for approvals. Always look at what executors are actually doing.
28A Worked Example: Taming a Slow Queue
Let us walk through a full improvement for a fictional company, step by step, without writing any code.
The situation
Larkspur Media has one Jenkins controller with twelve agents in a single pool, each with four executors. About a hundred and twenty developers use it. Every morning between nine and eleven, developers complain that builds wait fifteen to thirty minutes. Management’s first reaction is to buy twelve more agents.
Step by step
Measure before buying
The team charts queue length, queue time, and executor utilisation by hour for two weeks. Utilisation hits ninety-eight percent from nine to eleven, and the queue peaks at ninety items.
Classify the waiting
Most items are buildable, not blocked. But when they look at what busy executors are doing, they see that thirty executors are held by pipelines waiting for manual approvals, and eight by builds hung on a slow test service.
Fix the wasteful pipelines
They move approval steps outside agent blocks, so waiting no longer holds an executor. They add timeouts to steps that call the slow service. About thirty-eight executors are freed at once.
Reduce wasted demand
Analysis shows that a third of morning builds are older builds of pull requests that were updated again. They turn on automatic cancelling of superseded builds and lengthen the quiet period to thirty seconds for branch builds.
Stagger the schedules
Forty nightly and hourly jobs all start at zero minutes. Using the hash symbol spreads them across the hour.
Separate long from short
Three test suites that run for two hours each are moved to a dedicated pool of four agents, with a throttle limiting them to three at a time. Quick checks no longer wait behind them.
Speed up the top builds
The five most frequent builds get dependency caches and parallel test splitting, cutting their duration from twelve minutes to seven.
Add elasticity, capped
For the remaining morning peak, a Kubernetes template creates up to twenty extra agents, with a cap and an idle timeout of five minutes. Two permanent agents stay as a fallback.
Publish a target
The team publishes a goal: ninety percent of builds start within two minutes. A chart and an alert follow.
The result after one month
| Measure | Before | After |
|---|---|---|
| Peak queue length | About ninety items | About ten items |
| Typical morning wait | Fifteen to thirty minutes | Under two minutes |
| Peak utilisation | Ninety-eight percent | About seventy percent |
| Machines bought | Twelve proposed | None, plus a capped cloud burst |
Almost all the improvement came from cheap steps: looking at what executors were doing, cancelling waste, staggering schedules, and speeding up common builds. Buying machines would have hidden the causes and cost far more.
29Migrating from One Big Pool to Managed Pools
Many Jenkins installations start with a single pool where everything runs on everything. Here is how to move to managed pools without disruption.
What you may find
- Every agent has the same generic label, or none at all.
- Long jobs, quick jobs, and releases share the same executors.
- Executors were set to a round number years ago and never reviewed.
- Nobody knows which team uses how much capacity.
A safe migration path
Measure usage by job and team
Find which jobs consume the most executor time, how long they run, and when they run.
Group jobs into workload classes
For example: quick checks, standard builds, long test suites, special hardware, and releases.
Define a small label vocabulary
One label per class, documented, with a named owner.
Add labels to agents first
Give existing agents both the old generic label and the new one, so nothing breaks.
Move jobs class by class
Begin with the most damaging jobs, usually the long ones and the releases, and switch them to the new labels.
Rebalance agents
After watching queue times per pool, move agents between pools, or make some of them elastic.
Retire the generic label
When no job uses it, remove it, so new jobs must choose a class.
Splitting one pool into several always leaves some capacity idle in the wrong place. Expect a small drop in efficiency in exchange for predictable waits, and use elastic agents or shared overflow pools to soften it.
The reward
After migration, quick jobs no longer wait behind long ones, releases are protected, and each pool has an owner who can see and manage its own numbers.
30Governance: Owning the Queue Over Time
A queue that nobody owns slowly fills with rules, exceptions, and mysteries. Ownership and agreements keep it healthy.
Who owns what
| Area | Owner | Responsibility |
|---|---|---|
| Controller and global settings | Platform team | Executors on the controller, quiet period, plugins, upgrades |
| Agent pools and cloud templates | Platform team, with pool owners | Capacity, caps, images, costs |
| Locks, throttles, and priorities | Platform team | Documented, reviewed rules |
| Job and pipeline design | Application teams | Efficient builds, no idle waiting, sensible parallelism |
| Queue-time target | Engineering leadership and platform team | Agreeing on the goal and funding it |
Agreements to write down
- A queue-time target, such as ninety percent of builds starting within two minutes.
- A label policy: the approved labels, what they mean, and how to request a new one.
- A priority policy: who may use high priority, and for what.
- A pipeline standard: no waiting inside agent blocks, timeouts on long steps, limits on parallel branches.
- A rule for new rules: every lock or throttle needs a description, an owner, and a review date.
Regular reviews
Every quarter, look at the capacity sheet, the queue-time chart, the list of rules, and the ten biggest consumers of executor time. Retire old rules, fix the worst pipelines, and adjust capacity. Small, regular reviews prevent the slow drift into a confusing setup.
Visibility and accountability
Show each team its own usage: builds, executor hours, and waiting time. When teams can see their consumption, they take care of it. Some organisations also show the cost, which encourages efficiency without forcing central control.
Every rule has an owner
Locks and throttles without owners are future outages.
Measure before changing
Each change is justified by a number and checked afterwards.
Share the numbers
Dashboards are public inside the company.
Review quarterly
Remove rules that no longer earn their place.
A city traffic department watches the roads, changes signal timings, removes outdated signs, and publishes congestion maps. Nobody expects traffic to manage itself. A build queue needs the same continuing attention.
31Real-World and Industry Examples
These scenarios show how organisations manage their Jenkins queues. They are illustrative, so you can map them to your own situation.
Scenario: the approval that ate the pool
A company’s release pipeline pauses for a manager’s approval, and it does so inside an agent block. On Fridays, a dozen releases wait until Monday, holding a dozen executors all weekend. Monday’s developers wait in a long queue. Moving the approval outside the agent block frees the executors immediately, and the queue disappears.
Scenario: the test suite that starved everyone
One team’s end-to-end tests take three hours and run on every commit to a shared branch. Other teams’ quick checks wait behind them. The platform team creates a separate pool for long suites, throttles them to a fixed number, and changes the trigger so the tests run at most every thirty minutes. Everyone’s waits fall.
Scenario: the cloud bill surprise
A team enables elastic agents without a maximum. A script triggers thousands of builds by mistake, and hundreds of machines start. The next invoice shows a large charge. Afterwards, they add caps per template, a global cap, spending alerts, and per-tool API tokens so runaway scripts can be traced and stopped.
Scenario: the deadlock at Friday noon
Pipelines with nested agent blocks work fine all week. On Friday, many releases start together, every executor is taken by an outer block, and none of the inner blocks can start. The queue grows and nothing moves. The team rewrites the pipelines to use one agent block at a time and adds an alert for executors held for more than an hour.
Scenario: warm pools for fast feedback
A company measures that developers lose focus when builds take more than three minutes to start. It keeps a small warm pool of always-on agents sized for the average load, and lets elastic agents cover peaks. Median start time drops from four minutes to twenty seconds, and cloud costs rise only slightly.
What these examples share
In every good outcome, the team measured first, found a specific cause, and fixed it with a small, targeted change. In the bad outcomes, the queue was treated as a mystery, and the reaction was to add capacity or rules without understanding what was happening.
32How Other CI Tools Handle Queues
Every automation system has to match jobs to limited workers. Comparing them shows what is essential.
| Tool | How queuing and matching work | Notable difference |
|---|---|---|
| Jenkins | One queue on the controller, labels for matching, plugins for throttles, locks, and priorities | Very flexible; you assemble the policy yourself |
| GitHub Actions | Jobs wait for a runner that matches their labels, with concurrency groups to serialise or cancel runs | Concurrency groups with cancelling of older runs are built in |
| GitLab CI/CD | Jobs wait for runners chosen by tags, with resource groups to limit concurrency | Runner tags and resource groups are first-class settings |
| Buildkite | Agents pull work from named queues | Queues are explicit and agents choose which to serve |
| CircleCI | Jobs run on resource classes within a plan’s concurrency | Capacity is largely a plan setting |
Features change quickly, so check each tool’s current documentation before relying on this table.
What Jenkins does differently
In Jenkins the controller pushes work to agents, and one central scheduler decides. In some other systems, agents pull work from named queues. Jenkins gives you the freedom to compose rules from plugins and settings, and the responsibility to keep them understandable.
What is universal
The lessons apply everywhere: measure queue time, keep utilisation below saturation, separate long jobs from short ones, cancel superseded work, protect sensitive pools, cap elastic capacity, and make the reason for every wait visible.
33Advanced Topics: What to Learn Next
Once the basics feel comfortable, these ideas help larger and more cost-conscious organisations.
Predictive and scheduled scaling
Instead of waiting for the queue to grow, scale capacity ahead of known peaks. If demand rises every weekday at nine, raise the warm pool at eight forty-five. Some teams use history to predict demand and pre-start agents, trading a little idle cost for near-instant starts.
Cheaper, interruptible machines
Many clouds offer machines at a discount if you accept that they may be taken away with little warning. Builds are good candidates, because they can be retried. Combine such machines with retry rules for lost agents, and keep a base of stable machines for critical work.
Build caching and remote execution
The cheapest capacity is the build you do not run. Shared caches, and build systems that reuse results of unchanged parts, can cut build times dramatically. Some organisations go further and execute builds remotely on large pools of workers, which changes the shape of capacity planning.
Multiple controllers
Very large installations run several controllers, each with its own queue, agents, and teams. This limits the effect of any single failure and keeps each scheduler fast. It needs a shared standard and a central view of queue health across all controllers.
Custom queue behaviour
Jenkins allows plugins to influence how the queue is sorted and how items are assigned to nodes. Most teams never need custom logic, and the built-in features plus a few well-known plugins go a very long way. Consider custom work only after measurement shows a clear, recurring problem that nothing else solves.
Service level objectives
Treat queue time as a service level objective: a promise such as “ninety-five percent of builds start within three minutes,” with an error budget and a review process. This turns queue management into an engineering discipline with clear feedback.
Scheduled scaling
Warm up capacity before known peaks.
Interruptible machines
Cheaper agents that builds can survive losing.
Caching
Avoid repeating work that has not changed.
Service objectives
Promise, measure, and review queue time.
Add one advanced feature at a time, and only after the basics are measured and stable. A clever scaling scheme that nobody understands is another source of surprises.
34Troubleshooting Queue Problems
When something feels wrong, walk through these questions in order.
What does the queue say?
Read the reason next to the waiting item. It usually names the label, the rule, or the resource.
Blocked or buildable?
If blocked, find the lock, throttle, or running build that holds it. If buildable, look at capacity and labels.
Are matching agents online?
Check the nodes list for the requested label. Offline, disconnected, or missing agents are common causes.
What are the busy executors doing?
Look for builds that are waiting for approvals, hung on network calls, or running far longer than usual.
Is provisioning working?
For elastic agents, check the cloud logs, quotas, and template limits. A hit cap looks exactly like a shortage of capacity.
Is the controller healthy?
A slow web page or a scheduler that is not assigning free executors points to controller overload or a stuck thread.
Did something change recently?
Check recent edits to labels, schedules, throttles, plugins, and pipelines. Most queue mysteries follow a change.
| Symptom | Likely cause | First check |
|---|---|---|
| Item waits with no matching nodes | Label typo or missing agents | Label spelling and the nodes list |
| Free agents exist, but items wait | Label mismatch or throttle rule | Item’s requested label and rule messages |
| Executors full, CPU idle | Builds waiting inside agent blocks | What the busy builds are doing |
| Item stuck in handover | Agent connection trouble | Agent log and status |
| Queue grows at the same hour daily | Schedule stampede or morning peak | Schedules and arrival chart |
| Cloud agents do not appear | Cap reached, quota, or template problem | Cloud settings and provider errors |
Keep a short troubleshooting page for developers that explains the common queue messages in plain language and says whom to ask. It cuts a large share of support questions.
35Glossary of Terms
Every important word from this guide in one place, explained in plain language.
| Term | Plain meaning |
|---|---|
| Agent | A worker machine or container that runs builds for Jenkins. |
| Blocked item | A queue item held back by a rule, such as a lock or a running build of the same job. |
| Buildable item | A queue item ready to run, waiting only for a free executor. |
| Build queue | The waiting line of build requests on the Jenkins controller. |
| Category | A named group of jobs in the Throttle Concurrent Builds plugin that share a limit. |
| Concurrency limit | A rule limiting how many builds may run at the same time. |
| Controller | The central Jenkins server that owns the queue and schedules builds. |
| Deadlock | A situation where every party waits for another, so nothing can proceed. |
| Elastic agent | An agent created on demand and removed when idle. |
| Executor | One slot on a node that can run a single build at a time. |
| Fan-out | One event that creates many builds at once. |
| Jenkinsfile | The text file that defines a pipeline, stored beside the source code. |
| Label | A tag on an agent that lets jobs ask for a suitable machine. |
| Lock | A named resource that only one build may hold at a time. |
| Node | Any machine that provides executors, including the controller’s built-in node. |
| Pool | A group of agents that share a label and serve one kind of work. |
| Priority | A setting that lets some queue items go before others. |
| Quiet period | A short delay before a triggered build becomes ready, so repeated requests can merge. |
| Starvation | A job waiting far too long because others always go first. |
| Throughput | The number of builds completed in a period of time. |
| Utilisation | The share of capacity in use at a given time. |
| Warm pool | A few always-on agents kept ready for instant starts. |
| Webhook | A message sent by a code host to Jenkins the moment something happens. |
36Frequently Asked Questions
Short answers to the questions people ask most.
37Summary and Key Takeaways
Managing the build queue means matching demand to capacity, removing waste, and making every wait explainable.
You began with a busy coffee shop and finished with a clear picture of how Jenkins receives requests, holds them, matches them to executors and labels, and starts them. Along the way you learned the states of a queue item, how to read its reason, why waits explode near full utilisation, how to control concurrency, locks, and priorities, how to design pipelines that do not waste executors, how elastic agents fit in, and how to plan capacity, monitor, test, and govern the whole system. The main rules are simple: measure first, fix cheap causes before buying capacity, keep headroom, separate long work from short, and never hold an executor while waiting.
Key Takeaways
- The queue is a signal, not just a line. Read each item’s reason, and tell blocked items from buildable ones before choosing a fix.
- Keep the controller free of builds. Use zero executors on it, and size agent executors to cores and memory.
- Waits explode near full utilisation. Plan for peaks, keep about sixty to seventy percent utilisation at peak, and shorten builds before buying machines.
- Remove waste first. Cancel superseded builds, merge repeated requests, use webhooks, and stagger schedules with the hash symbol.
- Do not hold agents while waiting. Put approvals and waits outside agent blocks, avoid nested agent blocks, and limit parallel branches.
- Separate workloads. Use pools by job length, hardware, team, and criticality, and protect release and sensitive pools.
- Cap, monitor, and own it. Set maximums on elastic agents and build times, publish a queue-time target, alert on stuck items, keep settings in code, and review rules regularly.