5 Jenkins Pipeline Bottlenecks and How to Find Them
Your Jenkins builds are slower than they should be. Here are the five most common pipeline bottlenecks and how to identify them with data.
Your Jenkins build takes 12 minutes. It used to take 6. Nobody knows when it got slow or why. Sound familiar?
Pipeline performance degrades gradually. A slow stage here, an inefficient step there — each one adds 30 seconds, and before you know it, your team is waiting twice as long for every build.
Here are the five most common Jenkins pipeline bottlenecks and how to find them.
1. The silent stage regression
The problem: A single pipeline stage gets slower over time, but nobody notices because there's no trend data.
This is the most common bottleneck. A test suite grows from 200 to 800 tests. A Docker image adds new layers. A dependency resolution step starts downloading more packages. Each change adds a few seconds, and over weeks or months, a 45-second stage becomes a 4-minute stage.
How to find it: BuildButler's Pipeline Stages view shows scatter plots of stage duration over time. Each dot is a build, and you can visually spot stages where the dots are trending upward. The P95 boundary lines make it especially clear — when your P95 duration doubles, something changed.
How to fix it: Once you've identified the slow stage, the fix depends on what's in it:
- Test stage: Parallelize tests, remove redundant tests, or split into multiple stages
- Build stage: Add caching (dependency cache, Docker layer cache, build artifact cache)
- Deploy stage: Pre-build artifacts, use incremental deployments
2. Agent starvation
The problem: Builds queue up because there aren't enough agents — or because agents are unevenly utilized.
Jenkins distributes builds across agents, but it doesn't always do it efficiently. You might have 10 agents, but if 8 of your jobs are pinned to agents with a specific label, those 8 agents are overloaded while the other 2 sit idle.
How to find it: The Agents dashboard shows:
- Agent status (online/offline) and uptime over time
- Executor utilization per agent
- A 30-day reliability timeline showing when agents were available vs. down
If you see agents consistently at 100% utilization while others are idle, you have a distribution problem.
How to fix it:
- Review label assignments — make them as broad as possible
- Add auto-scaling agents (cloud-based agents that spin up on demand)
- Rebalance workloads across agent pools
3. Unnecessary sequential stages
The problem: Pipeline stages run one after another when they could run in parallel.
Many Jenkins pipelines are written sequentially by default. Lint, then build, then test, then scan, then deploy. But lint and build don't depend on each other. Neither do unit tests and static analysis. Running them sequentially wastes time.
How to find it: Look at your pipeline stage durations in BuildButler. If you have multiple stages with similar durations that don't depend on each other's outputs, they're candidates for parallelization.
The Compare Builds feature is useful here — compare a slow build against a fast one and see exactly which stages differ.
How to fix it: Use Jenkins' parallel directive:
This alone often cuts 30–40% off total pipeline time.
4. Flaky-test-driven retries
The problem: Flaky tests cause builds to fail and retry, effectively doubling (or tripling) build time.
If your pipeline retries on failure, and you have flaky tests, you're burning CI time on phantom failures. A 10-minute build that retries once becomes a 20-minute build — and if it retries twice, 30 minutes.
How to find it: BuildButler's Flaky Tests page shows exactly which tests are intermittently failing. Cross-reference with your build duration trends — if builds with retries are significantly longer, flaky tests are a bottleneck.
How to fix it:
- Fix the flaky tests (see our flaky test detection guide)
- As a short-term fix, quarantine known flaky tests so they don't block the pipeline
- Use selective retry (retry only the failed stage, not the entire pipeline)
5. Missing build caches
The problem: Every build starts from scratch, re-downloading dependencies, re-compiling unchanged code, and re-building Docker layers.
This is especially painful for large projects. A Node.js project with 2,000 dependencies spends 90 seconds on npm install every build. A Java project recompiles everything even when only one file changed. A Docker build re-runs every layer because the cache was invalidated.
How to find it: Look at stage durations for build and dependency-resolution stages. If they're consistently high and don't vary much between builds, caching is likely missing. In BuildButler's pipeline stages view, these stages show up as flat horizontal bands — same duration every time, no variation.
How to fix it:
- Dependency caching: Use Jenkins'
stash/unstashor a shared volume to cachenode_modules,.m2,.gradle, etc. - Docker layer caching: Use
--cache-fromwith a registry-stored image, or use BuildKit's cache mount - Incremental builds: Configure your build tool for incremental compilation (Gradle's
--build-cache, Maven's incremental compilation)
Measure, optimize, repeat
Pipeline optimization isn't a one-time project. Builds drift slower over time as codebases grow, dependencies change, and new stages are added.
The key is continuous measurement. With BuildButler's Pipeline Stages scatter plots and Build Results trends, you catch regressions as they happen — not three months later when someone finally asks "why are our builds so slow?"
Connect your Jenkins instance and find your bottlenecks today.