---
title: "dbt packages.yml: how it works and why to lock it | Metacenta"
description: "packages.yml lists the dbt packages a project installs. How to add hub, git and local packages, what dbt deps writes, and why to commit package-lock.yml."
url: "https://metacenta.com/rules/dbt-packages-unlocked"
updated: "2026-10-14"
tokens: 992
---

Repository hygiene · rule dbt-packages-unlocked

# dbt packages.yml: how it works and why to lock it

`packages.yml` lists the dbt packages your project installs. It sits beside `dbt_project.yml`. `dbt deps` reads it, installs each package and records what it resolved in `package-lock.yml`.

A Metacenta review checks this under the rule **dbt package versions are locked**. Everything below applies whether or not you ever commission one.

## What packages.yml does

Packages install into `dbt_packages/`, which git ignores. Their models and macros then become part of your project.

## How to add a package

Add an entry, then run `dbt deps`. Hub packages need a version, and they let dbt deduplicate dependencies that two packages share.

```yaml
packages:
  - package: dbt-labs/dbt_utils
    version: 1.3.0
  - git: "https://github.com/example-org/example_package.git"
    revision: 0.9.2
  - local: relative/path/to/package
```

## What dbt deps and package-lock.yml do

`dbt deps` creates or updates `package-lock.yml`. If `packages.yml` hasn't changed, later installs use the lock file. A version range pins to the latest matching release, and a branch pins to its head commit.

Newer versions aren't picked up until you run `dbt deps --upgrade`.

## packages.yml or dependencies.yml

Use `dependencies.yml` for dbt Mesh project dependencies, or to keep packages and projects in one file. Use `packages.yml` if you need Jinja on dbt v1, such as a git token from an environment variable.

See [dbt's packages docs](https://docs.getdbt.com/docs/build/packages) for the other entry types.

## What this rule checks

This rule flags a dbt project whose `packages.yml` or `dependencies.yml` has no `package-lock.yml` beside it. It passes if every package is pinned exactly: one version, a commit SHA, a version tag or a local path. Version ranges, git branches and packages with no version float, and we name those. Only the root-most dbt project is judged.

## Why it matters

Package versions resolve fresh on every install. Two CI runs a week apart can build the same project against different package code. A macro can change behaviour with nothing in the repository's history to show it.

## How to fix it

**Commit the dbt package lockfile.** Commit the `package-lock.yml` that `dbt deps` already writes, and change it only on purpose.

Before:

```yaml
# packages.yml, with no package-lock.yml beside it
packages:
  - package: dbt-labs/dbt_utils
    version: [">=1.0.0", "<2.0.0"]
```

After:

```yaml
# package-lock.yml, written by dbt deps and committed
packages:
  - package: dbt-labs/dbt_utils
    version: 1.3.0
sha1_hash: <written by dbt deps>
```

## When it is fine to leave

A project that pins every package to one exact version already passes, because it resolves the same way each time. Another sub-project in the repository, such as `integration_tests/`, is named in the finding as not examined.

## What we need to check it

The repository's file list, the packages file, and the dbt version from `manifest.json`. `package-lock.yml` exists from dbt 1.7, so without a manifest we decline, and older projects aren't judged. We also decline if the listing was truncated or the packages file could not be read. If it wasn't fetched at all, we report the missing lockfile without judging the pins.

[Ask about a review](https://metacenta.com/enquire?src=rule-dbt-packages-unlocked&via=md)

## Related pages

- [Credential files committed to a data repository](https://metacenta.com/rules/repo-committed-credential-file)
- [Data repository with no CI pipeline](https://metacenta.com/rules/repo-no-ci)
- [Archived repositories under review](https://metacenta.com/rules/repo-archived)
- [Data repository with no tests](https://metacenta.com/rules/repo-no-tests)
- [A sample review, as a client reads it](https://metacenta.com/sample)
- [All published rules](https://metacenta.com/rules)
- [How a review is assessed](https://metacenta.com/standard)
