Choosing a package type

Why flxbl projects default to source packages, and when to choose an unlocked, org-dependent unlocked, data, or diff package instead.

A flxbl project is organised into modules(packages). A module is a directory of metadata with a name, a version number, and a lifecycle; sfp builds it into an artifact and promotes that artifact through your environments. The package type determines how a module is built and how it is deployed. It does not determine whether the module is versioned, released, or tracked — those hold for every type.

Default to source packages. Choose another type when a specific requirement calls for it.

Why source packages are the default

Teams have historically organised metadata as source packages to begin with, then converted them to unlocked packages to gain incremental upgrades, scoped test runs, component ownership, and a build-time check that dependencies resolve. Those properties no longer require a Salesforce-managed package. sfp and codev provide them for source packages:

PropertyHow a source package has it
A versioned, immutable, traceable unitsfp builds every source package into a versioned artifact, through the same build path as any other type.
Deploys only the components that changedComponent checksum skip fetches the previously installed artifact and deploys only the components whose source bytes differ. On by default for source and diff packages.
Runs only the tests the change touchesWhen checksum skip reduces the deploy set, sfp sets the deploy test level to RunRelevantTests.
Detecting when an org no longer matches sourcecodev environment drift detection compares the source it expects on an environment against what the org actually contains.
Reconciling an org back to sourceSync redeploys branch state to an environment; a changeset captures an org-side change and raises it as a pull request against a tracked branch.
Removing components that left the moduleSource packages delete components through pre- and post-destructive entries.

A source package deploys through the Metadata API. It therefore covers every metadata type the Metadata API supports — a larger set than unlocked packaging — and it deploys without the package-version creation step, so its build is shorter.

When to choose an unlocked package

An unlocked package is a Salesforce-managed second-generation package version in addition to an sfp artifact. That platform-managed version is what an unlocked package adds over a source package, and it is the reason to choose one:

  • Component ownership across orgs. Salesforce locks each component to the package that owns it, so another package cannot overwrite it. A source package has no platform lock — ownership rests on your repository structure and on drift detection.
  • Build-time dependency validation. An unlocked package validates its declared dependencies when the version is created. A source package validates them at deploy time, against the target org.
  • Distribution outside your build. A package version can be installed into orgs you do not build from, by its subscriber package version id.

These come at a cost: creating a package version adds time to the build, each version is promoted before it can install to production, and moving a component from one package to another requires deprecation steps to release the platform lock. Choose an unlocked package where component ownership or build-time validation is worth that cost — shared libraries and frameworks that several packages depend on are the common case.

An org-dependent unlocked package skips build-time dependency validation and is source-deployed at install, so its build is faster than a standard unlocked package's. Component checksum skip applies to it as it does to a source package. It is a middle ground when unlocked build time is the only reason you would otherwise stay on source. See org-dependent unlocked packages.

The remaining types

  • A data package moves records rather than metadata. Use it for record-based configuration and reference data.
  • A diff package deploys only the metadata that differs from a baseline, for cases where deploying the whole module is not wanted.

Supported package types sets out the full behavioural comparison.

Changing type later

Package type is not a one-way decision. A module can start as a source package and become an unlocked package once its components are stable and you want platform-enforced ownership; environment-specific and org-specific metadata stays as source packages. The module boundary and its version history are unchanged by the switch — only how the module builds and deploys changes.

On this page