Choosing Between npm ci and npm install in CI/CD Pipelines
A decision guide that compares npm ci and npm install for reproducible, fast dependency installation in CI/CD pipelines.
09 Aug 2025, 21:18 UTC

Decision: npm ci vs npm install in CI/CD
When setting up a CI/CD pipeline you must decide how to install Node.js dependencies. The goal is a deterministic, fast build that respects the versions declared in package.json and recorded in the lockfile. The two main npm commands are npm ci (clean install) and npm install. This guide states the decision, lists constraints, compares the options, explains trade‑offs, and shows a concrete validation step.
Constraints
- The pipeline runs in a clean workspace (e.g., a fresh container or a newly cloned repository).
- A
package-lock.json(ornpm-shrinkwrap.json) must be present for reproducible installs. - Build speed matters, but not at the cost of introducing version drift.
- The pipeline should fail fast if the lockfile does not match
package.json.
Comparison
| Aspect | npm ci | npm install |
|---|---|---|
| Lockfile handling | Installs exactly as recorded; never updates the lockfile. | May update the lockfile when missing dependencies or when version ranges allow newer releases. |
Reading package.json |
Skipped; relies solely on the lockfile. | Read to resolve missing entries and to possibly update the lockfile. |
| Speed (with lockfile present) | Generally faster because it avoids the resolution step. | Slower on a fresh install due to full dependency resolution. |
| Safety in CI | Fails if lockfile missing or mismatched, preventing drift. | Succeeds even with a mismatched lockfile, potentially creating different node_modules. |
Effect on existing node_modules |
Removes the existing folder and installs a fresh tree. | Updates only missing or outdated packages; may leave extraneous files. |
Trade‑offs
Use npm ci when you need a guaranteed, reproducible build and the lockfile is committed to version control. It is ideal for CI pipelines that run on every commit or pull request. Choose npm install only when you intentionally want to update dependencies (e.g., a nightly upgrade job) or when you are working locally and want the lockfile to adapt to new version ranges.
Concrete implementation example
The following GitHub Actions workflow demonstrates a safe way to use npm ci and verify that the installed node_modules matches what a fresh npm install would produce.
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies with npm ci
run: npm ci
- name: Compute hash of installed node_modules
id: hash
run: |
find node_modules -type f -print0 | sort -z | xargs -0 sha256sum | sha256sum > ci.hash
echo "hash=$(cat ci.hash)" >> $GITHUB_OUTPUT
- name: Show hash
run: echo "CI hash: ${{ steps.hash.outputs.hash }}"
- name: Optional verification against npm install
if: false # set to true for a local test
run: |
# In a separate directory, run a full install and compare
cp -r . /tmp/npm-install-test && cd /tmp/npm-install-test
npm install
find node_modules -type f -print0 | sort -z | xargs -0 sha256sum | sha256sum > install.hash
if ! diff ci.hash install.hash; then
echo "Hash mismatch – lockfile may be outdated"
exit 1
fi
Limitations and practical checks
npm ciwill abort with a non‑zero exit code if the lockfile is missing or does not matchpackage.json. Treat this as a signal to regenerate the lockfile (e.g., runnpm installlocally and commit the updated lockfile).- The command removes the existing
node_modulesfolder, so any locally built native addons will be rebuilt. - To verify that
npm cirespected the lockfile, compare a content hash of the resultingnode_moduleswith a hash obtained from a freshnpm installin the same environment (as shown in the optional verification step). - Both commands honor
.npmrcsettings and the--omit=optionalflag; ensure your CI environment does not unintentionally exclude optional dependencies.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.