The dbt Hub is the standard distribution channel for open-source dbt packages — a registry, not a hosting platform. Packages live on GitHub; the Hub indexes their releases. As of early 2026, the ecosystem has over 400 packages covering source-specific transformations (Fivetran packages), testing utilities (dbt-utils, dbt-expectations), and monitoring tools (Elementary).
Requirements
Publishing to the Hub requires three things:
- The package is hosted on a public GitHub repository
- It has a
dbt_project.ymlwith anamefield - Releases use semantic versioning tags (e.g.,
v0.1.0)
That’s it. No special metadata, no separate manifest, no approval process beyond the initial PR.
The Registration Process
Getting your first version on the Hub is a four-step process:
-
Create a GitHub release with a semver tag. Tags like
first-release,beta, orlatestare ignored by the Hub’s indexer. Usev0.1.0,v1.0.0, etc. -
Open a pull request on the
hub.getdbt.comrepository to add your package to the index. The PR adds your repository to a JSON manifest. -
Wait for review. PRs are typically approved within one business day. The dbt Labs team does a basic sanity check — valid
dbt_project.yml, semver tags, public repo. -
Automatic updates after that. A script called
hubcapruns hourly to detect new GitHub releases automatically. No further PRs needed for version updates.
Once registered, new releases are picked up by hubcap within an hour of you creating a GitHub release. The cycle becomes: tag a release, push it, and the Hub updates itself.
How Users Install Hub Packages
Once published, users install your package with a version range in their packages.yml:
packages: - package: your-namespace/my_package version: [">=0.1.0", "<1.0.0"]The namespace is typically your GitHub username or organization. The version range lets dbt resolve the best compatible version automatically.
The Transitive Dependency Advantage
Hub packages have one significant advantage over Git packages: automatic transitive dependency resolution.
If your package depends on dbt-utils and the user’s project also depends on dbt-utils, the Hub reconciles version conflicts automatically. It picks the highest version that satisfies all constraints. Git packages can’t do this — version conflicts between Git dependencies require manual resolution, and the error messages are often cryptic.
This matters in practice because most non-trivial packages depend on dbt-utils. When a user has five packages installed and all five depend on dbt-utils, the Hub finds one version that works for everyone. With Git dependencies, you’d need to manually ensure compatibility.
Best Practices
The hubcap documentation lays out practices that the dbt Labs team has refined from maintaining the ecosystem:
Set require-dbt-version
require-dbt-version: [">=1.3.0", "<3.0.0"]Users should know compatibility upfront. Without this, someone on dbt 1.1 gets cryptic compilation errors instead of a clear “incompatible version” message. With the Fusion engine (dbt 2.0) now available, setting [">=1.3.0", "<3.0.0"] covers both runtimes.
Declare Hub Dependencies When Possible
If your package depends on dbt-utils, reference it from the Hub, not from Git:
# Good — enables transitive resolutionpackages: - package: dbt-labs/dbt_utils version: [">=1.0.0", "<2.0.0"]
# Avoid — breaks transitive resolutionpackages: - git: "https://github.com/dbt-labs/dbt-utils.git" revision: v1.3.0Hub dependencies participate in version resolution. Git dependencies don’t.
Use Wide Version Ranges
Don’t pin to patch versions. version: "1.3.0" forces every user to use exactly that version and creates conflicts with other packages that also depend on dbt-utils but expect a different patch.
# Too tight — creates dependency conflicts- package: dbt-labs/dbt_utils version: "1.3.0"
# Better — allows flexibility- package: dbt-labs/dbt_utils version: [">=1.0.0", "<2.0.0"]The wider the range that actually works, the fewer headaches for your users.
Don’t Override Global Behavior
Your package should not override dbt Core behavior that affects resources outside your package. Overriding generate_schema_name or generate_alias_name in a package changes behavior for the user’s entire project, not just your models. If you need custom behavior, scope it to your own models using the config() block.
Prefer Built-in Cross-Database Macros
Since dbt-utils v1.0, cross-database macros like datediff, dateadd, safe_cast, and hash live in the dbt namespace. Use {{ dbt.datediff(...) }} instead of reimplementing date arithmetic yourself. This reduces your dependency footprint and takes advantage of adapter-specific implementations that dbt Core maintains.
Semantic Versioning for Packages
Follow semver strictly:
- Patch (0.1.0 → 0.1.1): Bug fixes only. No behavior changes.
- Minor (0.1.0 → 0.2.0): New models, new macros, new features. Existing behavior unchanged.
- Major (0.2.0 → 1.0.0): Breaking changes — renamed models, removed macros, changed output schemas.
Pre-1.0 packages (0.x.y) can treat minor versions as breaking, which is common while you’re finding the right API. Once you hit 1.0.0, you’re committing to stability.
Maintain a CHANGELOG.md that documents what changed in each version. Users need to know whether upgrading from 0.3.0 to 0.4.0 is safe or requires migration steps.
When Not to Use the Hub
Not every package belongs on the Hub. Internal packages with proprietary business logic, packages that only work against a specific company’s data, and experimental packages that aren’t ready for community use are better distributed as Git packages. The Hub is for packages that solve a problem the broader community shares.