Skip to main content
When your project grows, installing dozens or hundreds of npm packages on every CI run can easily add minutes to your pipeline. By caching the node_modules directory in GitLab CI, you can reduce install time from ~7 s to ~1 s per job and save runner resources.

Example package.json for “Solar System” App

Here’s a simplified package.json for our Node.js service:
Running npm install generates package-lock.json and populates node_modules. In GitLab CI, each job running npm install repeats this process:

Cache vs. Artifacts

GitLab CI offers both cache and artifacts, but they serve different purposes:

Configuring cache:policy

Use the policy keyword to control download/upload behavior:
  • pull – only restore an existing cache
  • push – only upload a new cache
  • pull-push (default) – restore first, then upload after job success
The image shows a GitLab documentation page about the cache:policy keyword in CI/CD YAML syntax, explaining how to configure cache upload and download behavior with possible inputs like pull, push, and pull-push.

Adding Cache to .gitlab-ci.yml

Below is a minimal configuration that caches node_modules for unit_testing and code_coverage jobs:
Using package-lock.json in the cache key ensures the cache is invalidated automatically whenever your dependencies change.

Viewing the Pipeline

After committing .gitlab-ci.yml, GitLab triggers a pipeline. The Pipelines page shows status and stages:
The image shows a GitLab CI/CD pipeline interface with various pipeline statuses such as "Running," "Skipped," and "Failed." It includes details like pipeline IDs, branches, and user avatars.
Within the project view you’ll see jobs like unit_testing and code_coverage:
The image shows a GitLab CI/CD pipeline interface for a project named "Solar System NodeJS Pipeline," displaying the status of jobs like "code_coverage" and "unit_testing." The sidebar includes options for managing the project, such as issues, merge requests, and pipelines.

First Run: Cache Miss

On the initial run, no cache exists. The pipeline installs dependencies and then uploads the cache:
The image shows a GitLab CI/CD pipeline job interface with a successful unit testing job. The console output details the steps executed, and the job status is marked as "passed."

Subsequent Run: Cache Hit

With no changes to package-lock.json, the cache restores instantly and npm install completes in ~1 s:
The image shows a GitLab CI/CD pipeline job interface with a successful unit testing job. The console output displays steps like restoring cache, executing scripts, and uploading artifacts.

Clearing or Invalidating Cache

You can manually clear caches via Settings → CI/CD → Clear runner caches.
To automate invalidation, use package-lock.json in your cache:key as shown above.
Clearing caches too frequently may negate performance gains. Only clear when dependencies are truly out of sync.

Watch Video