Skip to content
All posts
Tutorial3 min read

package.json vs package-lock.json – What's the Difference?

DebuggerMe TeamDebuggerMe TeamApril 3, 2026
On this page

If you've worked with Node.js or npm, you've definitely seen package.json and package-lock.json sitting side by side in your project. Many developers know they're related to dependencies, but not everyone clearly understands why both exist and what makes them different.

Let's break it down.

What is package.json?

package.json is the project manifest file. It describes your project and lists the dependencies your application needs.

It typically includes:

  • Project name and version
  • Scripts (npm start, npm build, etc.)
  • Dependencies and dev dependencies
  • Metadata (author, license, etc.)

Example

json
{
  "name": "my-app",
  "version": "1.0.0",
  "dependencies": {
    "express": "^4.18.2"
  }
}

Key Point

When you write "express": "^4.18.2", the ^ means npm can install any compatible version, such as 4.18.2, 4.19.0, or any 4.x.x release.

This means installs may differ over time—which can cause problems.

What is package-lock.json?

package-lock.json is automatically generated by npm. It locks the exact versions of every installed dependency, including sub-dependencies.

It ensures:

  • Same dependency tree across all environments
  • Same versions for everyone on the team
  • Reproducible installs across machines

Example (simplified)

json
{
  "dependencies": {
    "express": {
      "version": "4.18.2",
      "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
      "integrity": "sha512-..."
    }
  }
}

This file guarantees that everyone installs the exact same version, even if package.json allows flexibility.

Main Differences

Featurepackage.jsonpackage-lock.json
PurposeDefines dependenciesLocks exact versions
Created byDevelopernpm automatically
Should you edit?YesNo
Version flexibilityYesNo
Included in Git?YesYes
Controls sub-dependenciesNoYes

Why Both Files Are Needed

Think of it like this:

  • package.jsonWhat you want
  • package-lock.jsonWhat you actually got

Example scenario:

  1. You install today → version 1.2.3
  2. Your teammate installs tomorrow → version 1.2.5
  3. App breaks due to subtle differences

With package-lock.json, everyone installs exactly 1.2.3—no surprises.

When Does package-lock.json Update?

It updates when:

  • You run npm install
  • You add or remove packages
  • You run npm update

Should You Commit package-lock.json?

Yes—always commit it to Git.

Benefits:

  • Reproducible builds
  • Faster installs (npm can skip resolution)
  • Prevents "works on my machine" issues

Quick Analogy

  • package.json = Shopping list
  • package-lock.json = Receipt with exact brands and quantities

Conclusion

Both files serve different but complementary purposes:

  • Use package.json to declare what dependencies you need
  • Use package-lock.json to guarantee everyone gets the same versions

Never delete package-lock.json unless you intentionally want to regenerate your entire dependency tree.

DebuggerMe Team

Written by

DebuggerMe Team

The DebuggerMe team builds developer tools, writes technical content, and helps teams ship better software.

Share this post

Back to all posts

Related Articles

All articles →