Cut Build Times in Azure DevOps Pipelines with the Cache Task
Long CI runs bog down feedback loops. Azure DevOps’ Cache task lets you store and restore dependency folders between runs, shaving minutes off each build. This guide walks through the key concepts, YAML setup, a live example, trade‑offs, and next steps to keep your pipelines fast and reliable.
02 Oct 2025, 10:29 UTC

Problem: Long CI Runs Drag Your Feedback Loop
In a typical CI pipeline you install dependencies, compile code, run tests, and publish artifacts. For large projects, the “install” step can consume 30‑60% of the total run time. Every commit that triggers a pipeline pays that cost, which means developers wait longer for results and the build agent queue builds up. Azure DevOps offers a built‑in solution called the Cache task that can store and restore a directory between runs, eliminating the need to reinstall unchanged dependencies.
How the Cache Task Works
- The task runs at the start of a job and attempts to restore a folder from a cache store that matches a supplied key.
- If a cache entry exists, the task copies the folder into the agent’s working directory and logs
Cache hit. If not, it logsCache missand the folder remains empty. - After the job completes, the task uploads the folder back to the cache using the same key, unless the folder was not modified.
- Only non‑sensitive data should be cached because the cache is shared across all pipelines that use the same key.
Key Configuration Steps
There are three essential pieces you need to provide:
- Key – a string that uniquely identifies the content of the folder. A common pattern is to include a checksum of a lock file (e.g.,
package-lock.jsonorpom.xml). This ensures that changes to dependencies trigger a cache miss. - Path – the relative location of the folder you want to cache. For Node projects this is usually
node_modules; for Maven it’s~/.m2/repositoryor thetargetdirectory. - Restore‑keys – optional fallback keys that allow partial restores when the primary key fails. Useful when you want to reuse a previous cache even if the lock file changes slightly.
Worked YAML Example
The following pipeline demonstrates a simple JavaScript/TypeScript build that also compiles a .NET library. It caches node_modules and the Maven target folder to speed up subsequent runs.
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- task: Cache@2
inputs:
key: 'npm | $(Agent.OS) | package-lock.json'
path: $(Pipeline.Workspace)/node_modules
displayName: 'Cache npm modules'
- script: |
npm ci
npm run build
displayName: 'Install and build JS'
- task: Cache@2
inputs:
key: 'maven | $(Agent.OS) | pom.xml'
path: $(Pipeline.Workspace)/maven-target
displayName: 'Cache Maven target'
- script: |
mvn -B clean package
displayName: 'Build .NET project'
- publish: $(Pipeline.Workspace)/maven-target
artifact: MavenTarget
displayName: 'Publish Maven target'
After the first run, you will see Cache miss messages and the folders will be populated. Subsequent runs that do not modify package-lock.json or pom.xml will hit the cache, skipping installation and compilation steps. The log will contain Cache hit and the total run time will drop noticeably.
Trade‑Offs and Limitations
- Cache Size Quota – Each Azure DevOps organization has a maximum cache size (default 50 GB for services, configurable for server). If you exceed it, older entries are evicted, which can turn a hit back into a miss.
- Key Collision Risk – Reusing the same key across projects can cause one project’s cache to overwrite another’s. Always include a project‑specific prefix or use a unique lock file hash.
- Stale Data – If you change a dependency without updating the lock file, the cache will still hit. Ensure your key includes all files that influence the folder’s contents.
- Non‑Sensitive Data Only – Cached content is accessible to any pipeline that matches the key. Never cache credentials or secrets.
How to Verify the Cache Is Working
- Run the pipeline once and note the
Cache misslog entries. - Run it again; the logs should show
Cache hitfor each cache task. - Check the Azure DevOps portal: navigate to Project Settings > Pipelines > Cache and confirm the stored key and size.
- Use a script task to list the cached folder’s contents after a successful run:
This confirms the folder was restored.script: ls -la $(Pipeline.Workspace)/node_modules
Actionable Next Steps
- Audit your pipelines for repetitive dependency installs and add a Cache task where appropriate.
- Define a key strategy that includes a hash of every lock file that influences the folder.
- Monitor cache usage in the portal and adjust the cache size quota if you hit the limit.
- Document cache keys in your README so new contributors understand why a key is structured the way it is.
Conclusion
Azure DevOps’ Cache task is a straightforward, declarative way to cut CI build times by reusing previously downloaded dependencies. By carefully designing cache keys, respecting size limits, and validating hits, you can maintain fast feedback loops without adding complex tooling to your pipeline.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.