Package Dependency
A package dependency is a relationship where the metadata in one Salesforce package relies on metadata that lives in another package.
Definition
A package dependency is a relationship where the metadata in one Salesforce package relies on metadata that lives in another package. The package that supplies the shared components is the base package, and the package that builds on top of it is the dependent package, often called an extension. The base must be present in an org before its dependent package can install or work correctly.
Dependencies are how a partner extends a base app with separate, specialized features instead of cramming everything into a single package. In second-generation managed packaging (2GP) and unlocked packaging, you declare each dependency explicitly in the sfdx-project.json file, so every developer can see exactly what a package needs.
How package dependencies shape Salesforce app architecture
What a dependency actually means
A dependency exists the moment one package references a component owned by another. Imagine a base package that defines a custom object and a few Apex classes. A second package adds a Lightning component and a trigger that read from that object. The second package cannot compile or install on its own, because the object it points to is not there yet. That reference is the dependency. Salesforce tracks these relationships so installs stay consistent. The base package has to be in the target org first. Once a dependent package is installed, the platform protects the base from changes that would break the extension. You cannot uninstall the base while a dependent package still points at it. The org returns an error to the effect that the extension depends on the package you are trying to remove. Dependencies are not limited to one hop. A package can depend on several others, and those can have their own dependencies, forming a chain. Mapping that chain before you install or release anything saves you from confusing mid-install failures and missing-component errors.
Base packages and extension packages
Two roles describe almost every dependency. The base package holds the shared foundation, things like core objects, fields, and reusable Apex that several features build on. The extension package adds capability on top, referencing the base rather than copying it. This split lets one team own the foundation while other teams ship features at their own pace. ISV partners lean on this pattern heavily. A vendor might ship one base package with common data structures, then sell or release multiple extensions for different industries or add-on features. Customers install the base once, then add only the extensions they need. Shared logic lives in a single place, so a fix to the base reaches every extension without duplicate work. The trade-off is coordination. An extension is pinned to a specific base version, so the base team and the extension teams have to agree on version compatibility. When the base ships a new version with changed components, extension authors test against it before they release a matching update. Good architecture keeps the base stable and narrow so it does not churn under the extensions.
Declaring dependencies in sfdx-project.json
With 2GP and unlocked packages, dependencies are explicit, not guessed. You list them in the dependencies section inside packageDirectories in the sfdx-project.json file. Each entry identifies the package a build relies on, either by package alias plus a versionNumber, or by the exact subscriberPackageVersionId (the 04t ID) of the version you want. Using a versionNumber such as 1.2.0.LATEST lets the build resolve to the newest matching version, which helps during active development. Pinning the 04t ID locks the build to one specific version, which gives you repeatable, predictable results for a release. Many teams develop against LATEST and pin an exact ID when they cut a production version. This explicit declaration is one of the real advantages of modern packaging. Anyone reading the project file can see every managed 1GP or 2GP package the current package needs. The Salesforce CLI uses that list when it creates a new package version, pulling in the declared dependencies so the version builds against the right foundation. First-generation packaging had no equivalent, which made dependency tracking far more manual and error prone.
Which package types can depend on which
Not every combination is allowed, so the package type you choose decides what you can build on. A second-generation managed package can declare a dependency on another 2GP managed package and on a first-generation managed package. That lets a 2GP extension build on a base that already ships through the older 1GP model, which matters for partners migrating gradually. Unlocked packages are the most flexible on this front. A single unlocked package can depend on multiple other unlocked packages, plus first and second-generation managed packages. Teams use unlocked packages to break a large org into small, interdependent modules that share logic cleanly. The base side has rules too. To be a dependency target, the base usually needs a released, installable version with a stable namespace, not a throwaway beta. Mixing namespaces and ownership across an ecosystem takes planning, because once customers install a chain of packages, the relationships are hard to unwind. Checking the supported combinations early, against the current Salesforce documentation, keeps you from designing a structure the platform will not let you ship.
Installation order and uninstall protection
Dependencies force an order on both ends of a package lifecycle. On install, the base goes in before the dependent package. A common production approach is a script that queries for the dependencies, then installs each package in the correct sequence so nothing fails for a missing component. Salesforce publishes a sample install script for exactly this, because doing it by hand across a chain is tedious and easy to get wrong. On uninstall, the order reverses. You remove the dependent packages first, then the base. The platform enforces this by blocking removal of any package that still has something depending on it. If you try to uninstall a base while an extension is present, you get a clear error naming the conflict. This protection is a feature, not a nuisance. It stops an admin from accidentally deleting the foundation that live functionality still needs. The practical habit is to know your full dependency graph before you touch any package in a production org, so a routine cleanup does not stall halfway through with components you cannot remove yet.
Releasing and versioning with dependencies in play
Promoting a package that has dependencies adds a few questions you should answer before you ship. The biggest one is which version of the base each release targets. Once you promote and release a version, customers install it, so the dependency it carries is effectively locked for those subscribers until they upgrade. Salesforce documents specific considerations for promoting packages with dependencies, and the spirit of them is simple. Make sure the base version you depend on is itself released and installable, not a beta that subscribers cannot get. Confirm the dependency chain still resolves after any base change. Decide whether a base update is backward compatible, because if it is not, your extension may need a coordinated release. Version numbers carry weight here. The four-part versionNumber (major.minor.patch.build) signals the size of a change to both your team and your customers. Keeping the base stable, communicating version requirements in your install guide, and testing the full install order in a clean org before release are what separate a smooth upgrade from a support ticket about missing components.
Trust & references
Cross-checked against the following references.
Straight from the source - Salesforce's reference material on Package Dependency.
Hands-on resources to go deeper on Package Dependency.
About the Author
Dipojjal Chakrabarti is a B2C Solution Architect with 29 Salesforce certifications and over 13 years in the Salesforce ecosystem. He runs salesforcedictionary.com to help admins, developers, architects, and cert/interview candidates sharpen their fundamentals. More about Dipojjal.
Test your knowledge
Q1. What is a Package Dependency?
Q2. When are dependencies common?
Q3. What does dependency mean for installation?
Discussion
Loading discussion…