Unlocked Packages for Customers

Break Up Your Metadata

Describe how enterprise customers use unlocked packages. Describe how package development is different from change set development. Describe how you deploy metadata using packages.
  • Why Package Development is the Future
    • Change set development: traditional development model that uses the ANT Migration Tool, change sets, or unmanaged packages.
      • Development occurs within confines of a sandbox or production org.
      • “Source of Truth” is the production org, even if changes are tracked externally in a version control system.
    • Package Development: new and improved source of truth is your version control system.
      • Use Salesforce DX projects to organize source into package directories, with the end goal of creating packages using those directories that are versionable and there fore easy to maintain/update/install/upgrade.
  • What is a Package?
    • Packages are containers that you fill with metadata, or a “distributable unit of functionality”
    • Most compelling reason to use packages comes down to organizing your metadata
  • Unlocked Packages to the Rescue
    • Unlocked Packages are especially suited for internal business apps. They help you add, edit, and remove metadata in your org in a trackable way so you can reuse components
    • To track changes you create version of your package. Each version is an immutable artifact - a snapshot of the contents of the package.
  • What is an Unlocked Package?
    • Unlocked packages give you the flexibility to make changes directly in the production org, so admins can make emergency change requests
    • Unlocked packages are developer-controlled
      • Installation of any new package version overwrites any changes made directly in the production org, so it’s critical that admins communicate any direct changes to the development team so the package is updated appropriately.
    • Almost all types of Salesforce metadata and components can be put in an unlocked package. The Metadata Coverage report has all the details.
  • How do you Get Started?
    • Package development can be adopted incrementally:
      • If starting out with a lot of undifferentiated source, you can adopt packaging by slowly carving up your metadata to organize it into logical containers
      • Start small by packaging components and schema that you can later reuse in multiple apps
    • Later, you can define dependencies between the packages

Package Development with Salesforce DX

  1. Developer modifies metadata in the project, and changes accumulate. Scratch orgs used to develop and unit test the changes. Release manager creates a package version and shares it with QA.
  2. Quality Assurance (QA) installs the package and gets to work. Developer also uses the package for unit testing and CI. During process, bugs are fixed, features added and modified. Sometimes, you create a new package version and start the unit testing process (step 1) again.
  3. Finally, QA and Developer agree you have a good version, then you install it in your sandbox for User Acceptance Testing (UAT) and finally in production.
    • Installing the package version is similar to deploying metadata - you install a package version in any org (scratch, sandbox or production) similar to deploying a set of metadata.
  • Now that you Released Your First Package
    • The next release is usually urgently needed
    • Create all the new version you need as you change, add, or remove package metadata.
    • Each package version has a version number (like and you can use a package upgrade to apply these changes to an installed package version
    • Process (modify metadata -> create package version -> test package version -> deploy to production) can repeat any number of times

  • Unlocked packages are primarily designed for Customers who develop and deploy in-house business apps
  • The Package Development model is an iterative process where you organize metadata into packages
  • You deploy metadata in this new model to sandboxes for UAT by installing the package version in the org
  • Unlocked packages provide flexibility to make changes directly in the org

Build Your First Unlocked Package

Become familiar with CLI commands for packaging. Describe the basic packaging use cases. Package the DreamHouse LWC sample app and install it in a Trailhead Playground.
  • Why We Love Package Development
    • Follows best practices regarding the software development lifecycle. It’s compatible with the features of Salesforce DX: projects, CLI commands, and scratch orgs were built specifically with packaging in mind.
    • Encapsulates all the changes you’re tracking between lifecycle stages in a versioned artifact.
    • Makes it easier for you to accommodate new feature requests. Simply add, update, and remove components in your package.
    • Provides an improved audit history, so you can track and understand the changes made to your production org.
    • Organizes source. It’s much easier to know which components belong to which applications and features.
    • Promotes iterative and modular development.
    • Supports interdependencies among unlocked packages.
      • A single unlocked package can depend on multiple unlocked packages, and first and second-generation managed packages.
    • Supports continuous integration and continuous delivery because the packaging CLI commands enable each step in the deployment pipeline to be fully automated.
  • Configure Your Environment
    • Requires a clean Trailhead Playground with:
      • Dev Hub enabled
      • Unlocked Packages and Second-Generation Managed Packages Enabled
      • Known credentials for subsequent steps
    • GitHub
    • Salesforce CLI
  • “Git” the DreamHouse Source Code
git clone https://github.com/dreamhouseapp/dreamhouse-lwc.git

  • Configure Your Package
    1. Authorize your Dev Hub with the following command: sfdx force:auth:web:login -d -a DevHub
    2. Double check that the Dev Hub org is connected: sfdx force:org:list
    3. Replace the contents of sfdx-project.json with the following, but preserve the sourceApiVersion number in the original code snippet.
   "packageDirectories": [
         "path": "force-app",
         "default": true
   "namespace": "",
   "sfdcLoginUrl": "https://login.salesforce.com",
   "sourceApiVersion": "54.0"
  • Why Aren’t We Using a Namespace?
    • Package Namespaces are optional for unlocked packages, but including one helps you keep the package components organized
    • If migrating from an org that’s never used unlocked packages to unlocked packages, created your packages without a namespace. This way, when metadata is moved from an unpackaged state to an unlocked package, the API name of the metadata elements doesn’t change.
  • Create the Package
    1. From the dreamhouse-lwc folder, create an unlocked package without a namespace, and supply the alias for your Dev Hub org if it’s not already the default: sfdx package:create --name dreamhouse --description "My Package" --package-type Unlocked --path force-app --no-namespace --target-hub-org DevHub
      • --name is the package name
      • --path is the directory that contains the contents of the package
      • --packagetype indicates which kind of package you’re creating, in this case, unlocked
    2. Open sfdx-project.json. Note that it:
      • Now contains the package name you defined, which placeholders for the version name and number.
      • Also creates a packageAliases section, which maps the package name to the corresponding package ID (0Ho)
      • Note: If you forget the package alias or package ID, you can list all the packages associated with your Dev Hub by running sfdx force:package:list

  "packageDirectories": [
      "path": "force-app",
      "default": true,
      "package": "dreamhouse",
      "versionName": "ver 0.1",
      "versionNumber": "0.1.0.NEXT",
      "versionDescription": "My Package"
  "namespace": "",
  "sfdcLoginUrl": "https://login.salesforce.com",
  "sourceApiVersion": "57.0",
  "packageAliases": {
    "dreamhouse": "0HoDm000000KyjBKAS"
  • Create a Scratch Org to Test Your Package Version
    • Create a scratch org with the alias MyScratchOrg using: sfdx force:org:create --definitionfile config/project-scratch-def.json --durationdays 30 --setalias MyScratchOrg -v DevHub
  • Create the Package Version and Install It in Your Scratch Org
    1. Open sfdx-project.json and update the package version options. VersionName = “Version 1.0” and versionNumber = “1.0.0.NEXT”
    2. In the dreamhouse-lwc folder, create the package version, which associates the metadata with the package: sfdx force:package:version:create -p dreamhouse -d force-app -k test1234 --wait 10 -v DevHub
      • -p is the package alias that maps to the package ID
      • -d is the directory containing the package contents
      • -k is the installation key that protects your package from being installed by unauthorized people
      • Note that after running the command the packageAliases section has a new entry:
    3. Use the package version alias to install the package version in the scratch org: sfdx force:package:install --wait 10 --publishwait 10 --package [email protected] -k test1234 -r -u MyScratchOrg
    4. Open the scratch org to view the package: sfdx force:org:open -u MyScratchOrg
    5. Note the installed package from “Installed Packages” in the scratch org
  "packageDirectories": [
      "path": "force-app",
      "default": true,
      "package": "dreamhouse",
      "versionName": "Version 1.0",
      "versionNumber": "1.0.0.NEXT",
      "versionDescription": "My Package"
  "namespace": "",
  "sfdcLoginUrl": "https://login.salesforce.com",
  "sourceApiVersion": "57.0",
  "packageAliases": {
    "dreamhouse": "0HoDm000000KyjBKAS"

  "packageDirectories": [
      "path": "force-app",
      "default": true,
      "package": "dreamhouse",
      "versionName": "Version 1.0",
      "versionNumber": "1.0.0.NEXT",
      "versionDescription": "My Package"
  "namespace": "",
  "sfdcLoginUrl": "https://login.salesforce.com",
  "sourceApiVersion": "57.0",
  "packageAliases": {
    "dreamhouse": "0HoDm000000KyjBKAS",
    "[email protected]": "04tDm000000XzcYIAS"

  • Release the Package Version
    • Packages have beta status when you create them. You can’t install beta packages in a production org. This is a safeguard to make sure the package version you release is production ready.
    • Package version promotion command looks like: sfdx force:package:version:promote -p [email protected] -v DevHub
  • Install the Package Version in an Org
    • You can install a released package version in any org. Instructions to install the package in a Trailhead Playground follow.
    1. Add the Trailhead Playground to your list of authorized orgs: sfdx auth:web:login -a MyTP. You will be prompted to log in.
    2. Install the package version in the Trailhead playground: sfdx force:package:install --wait 10 --publishwait 10 --package [email protected] -k test1234 -r -u MyTP
    3. Open the Trailhead Playground: sfdx force:org:open -u MyTP and check the “Installed Packages

Organize Your Metadata

List the key strategies for organizing unpackaged metadata into packages. Identify how unlocked packages can be interdependent. Describe the 3 package development models, and when to use each.
  • Put the Principles of Package Development into Practice
    • Organizing metadata into packages:
      • Is often an iterative process
      • Is not an all-or-nothing proposition
  • DreamHouse Metadata
    • Schema: includes custom objects for Broker , Property , and Favorite Ex: Broker__c, Property__c, Favorite__c
    • Lightning Applications and Components: explore properties and property details. Ex: Property_Explorer.flexipage-meta.xml, Property_Record_Page.flexipage-meta.xml
    • Processes (Flows): Send notifications when new properties are added or the prices has changed. Ex: Advertise_New_Property-2.flow-meta.xml, Price_Change_Push_Notification-1.flow-meta.xml
    • Einstein services: Apply image processing to automatically discern home details from images that are uploaded. Ex: EinsteinVisionController.cls
    • Bots: Allow customers to engage via Facebook Messenger, Slack, or Alexa to search for properties. Ex: HandlerFindProperties.cls
  • Break Up Your Org’s Existing Metadata
    • Approaching breaking up unpackaged metadata into packages is one part science and one part art, but the following questions may help get started:
      1. Would the development team like to be able to release certain apps, new features, and customizations independently?
      2. Can a set of metadata that represents an app be identified?
      3. Can you organize metadata into modules for distinct features?
      4. When you create an unmanaged package for this feature or app, what dependencies are you seeing?
  • Three Models for Untangling Your Metadata
    • App-based: Identify metadata that represents an app
    • Customizations-based: Organize unpackaged metadata for customization and functionality changes in your production org, such as Sales Cloud, Service Cloud, or an AppExchange App
    • Shared Library: when interdependencies exist, use a common Salesforce DX package to organize a set of Apex classes or commonly used custom objects. Other packages that you construct can be depend on this common package.
  • Use an Unmanaged Package as a Starting Point
    • A starting workflow to organize unmanaged metadata into packages:
      1. Select a small set of unpackaged, self-contained metadata from your production org. Select metadata that represents an app, a customization to an existing app, a feature or functional unit, or customizations to standard objects.
      2. Create an unmanaged package to isolate the metadata you’ve identified from the overall collection of org metadata. As you add metadata to it, see which dependent metadata is automatically pulled in by the system. This step helps in unearthing some not-so-obvious dependencies among your metadata.
      3. Retrieve the source from your unmanaged package using force:mdapi:retrieve
      4. Set up a Salesforce DX project and a git repository to manage the package metadata
      5. Push this metadata to a scratch org using force:source:push and validate that this is the metadata that you want to be part of an unlocked package
      6. Create an unlocked package using the --nonamespace flag
      7. Test and deploy the unlocked package
      8. Once the unlocked package has passed all CI runs and UAT on sandboxes, promote the package version
      9. Install the unlocked package in the production org
  • About Package Dependencies
    • Unlocked packages can depend on an AppExchange package
    • Unlocked packages can depend on other unlocked packages, which in turn can depend on another unlocked packages. Multiple levels are supported
    • Express dependencies in the packageDirectories section of the sfdx-project.json file. By supporting dependencies, unlocked packages promote modular development with a rich dependency framework.

  • When you first start organizing your metadata into packages, you should identify a set of related metadata that represents a functional unit
  • Unlocked packages can depend on another unlocked package and/or an AppExchange app
  • If you are customizing Sales Cloud so that it shares some functionality with Service Cloud, which model would you select? Customizations-based and Shared Library