SFX Support Header
logo

Salesforce Packaging - Distributing & Managing Customizations

Understand Salesforce packaging, a fundamental concept for distributing and managing your customizations. Learn about Unmanaged, Managed (1GP & 2GP), and Unlocked Packages, and how to create them easily.

Need hands-on training?

1. Introduction to Salesforce Packaging

In Salesforce development, once you've built custom functionalities like Apex code, Lightning Web Components, custom objects, or flows, you often need to move these customizations between different Salesforce environments (e.g., from a Sandbox to Production) or distribute them to other Salesforce organizations. This is where Salesforce Packaging comes in.

Salesforce packaging allows you to bundle your metadata (your customizations) into deployable units. These packages can then be installed into other Salesforce organizations, streamlining the process of distribution, deployment, and version management of your applications or components.

Why is Packaging Important?

  • Distribution: Easily share your custom solutions with other Salesforce organizations.
  • Version Control: Manage different versions of your application or components.
  • Deployment: Simplify the process of moving changes across environments or to customers.
  • Intellectual Property Protection: For commercial applications, protect your source code.
  • Modularity: Break down large implementations into smaller, manageable, and reusable units.

This module will explain the different types of Salesforce packages – Unmanaged, Managed (1st Generation and 2nd Generation), and Unlocked Packages – highlighting their characteristics, use cases, and how to create them.

2. Unmanaged Packages

Unmanaged packages are the simplest type of package and are primarily used for distributing open-source projects, templates, or small, self-contained applications. Think of them as a "copy-paste" mechanism for Salesforce metadata.

  • Description: An unmanaged package bundles a collection of metadata components. Once installed in a target organization, these components become fully editable and belong entirely to the installing organization. There's no ongoing connection or upgrade path from the original developer.
  • Key Characteristics:
    • Editable: All components (Apex, LWC, custom objects, etc.) are fully customizable by the installing organization.
    • No Upgrade Path: There's no built-in mechanism for the original developer to push updates or new versions to installed unmanaged packages. If you want to update, you typically have to manually re-deploy the changes or install a new version, which might overwrite local changes.
    • No Intellectual Property Protection: The source code of Apex classes, Visualforce pages, etc., is visible and accessible after installation.
    • No Namespace: Components within an unmanaged package do not have a unique namespace prefix. This means there's a higher risk of naming conflicts if the installing org already has components with the same name.
    • Deletion: Uninstalling an unmanaged package removes the package container, but the installed components remain in the target org. You have to manually delete the components.
  • Use Cases:
    • Sharing sample code or templates with other developers.
    • Distributing open-source projects or utilities.
    • Providing a starting point for a customer's implementation that they will then customize heavily.
    • Migrating components between non-related developer orgs (though Change Sets or SFDX are often preferred for internal orgs).
  • How to Create (Declarative - via Salesforce UI):

    This is the easiest way for admins or developers to create a quick unmanaged package.

    1. Log in to your Salesforce Developer Edition or Sandbox org where your customizations reside.
    2. Go to Setup.
    3. In the Quick Find box, type Package Manager and select Package Manager (or Packages).
    4. Click the New button under "Unmanaged Packages".
    5. Provide a Package Name (e.g., "MyUtilityComponents") and optionally a description. Click Save.
    6. On the Package Detail page, click Add Components.
    7. Select the Component Type (e.g., Apex Class, Custom Object, Lightning Web Component) and then select the specific components you want to include. Click Add To Package. Repeat for all components.
    8. Once all components are added, click the Upload button.
    9. Review the package details and click Upload again. Salesforce will provide an installation URL that you can share.
  • How to Create (SFDX CLI - Integration with UI):

    While the SFDX CLI does not have a direct command to *create* an unmanaged package container, it is instrumental in preparing your source code for unmanaged package creation via the Salesforce UI. You manage your source code in an SFDX project, push it to a development org (sandbox or scratch org), and then use the declarative UI to create the unmanaged package from that org. Alternatively, the Ant Migration Tool can be used with a package.xml to deploy components, which effectively acts as an unmanaged deployment.

    # SFDX is primarily used for source-driven development and 2GP.
    # For unmanaged packages, the typical SFDX workflow involves:
    # 1. Developing your customizations in a scratch org or sandbox.
    # 2. Pulling the source to your local SFDX project:
    #    sf project retrieve start -o myDevOrg
    # 3. Then, you use the Salesforce UI (Package Manager) in that same org to create the unmanaged package,
    #    selecting the components that are now present in the org from your SFDX project.
    # Alternatively, for programmatic unmanaged deployments, you could use the Ant Migration Tool
    # with a package.xml to deploy source to another org.
    

3. Managed Packages (1st Generation & 2nd Generation)

Managed packages are the cornerstone for Salesforce ISVs (Independent Software Vendors) to distribute and sell their applications on the AppExchange. They offer crucial features like intellectual property protection, upgrade capabilities, and a unique namespace.

  • Key Characteristics (Common to both 1GP and 2GP Managed):
    • Protected Components: The source code of Apex classes, Visualforce pages, and other intellectual property is hidden from the installing organization. Components are generally not editable after installation.
    • Upgrade Path: The package developer can push upgrades to installed managed packages, allowing customers to receive new features and bug fixes.
    • Unique Namespace: All components within a managed package have a unique namespace prefix (e.g., mycompany__MyComponent__c). This prevents naming conflicts with components in the installing organization or other managed packages.
    • AppExchange Distribution: Required for listing applications on the Salesforce AppExchange.
    • Version Control: Strong versioning capabilities, allowing for clear release management.

a. 1st Generation Managed Packages (1GP):

  • Description: This is the traditional way to create managed packages, typically developed in a single Developer Edition org (often called a "packaging org"). It's an org-centric development model.
  • Development Model: Org-based development. You develop your metadata directly in a special Developer Edition organization, which then becomes your packaging org. All components for the package must reside in this single org.
  • Limitations:
    • Can be difficult to manage for large, modular applications as all components are in one monolithic package.
    • Limited direct integration with modern source control practices for package definition.
    • No support for scratch orgs.
    • Dependencies between packages are harder to manage.
  • Creation (High-Level - via Salesforce UI in a Packaging Org):

    1GP creation is done primarily through the Salesforce UI in a special Developer Edition org that you designate as your packaging org.

    1. Request a special Developer Edition org for packaging (if you don't have one).
    2. Develop all your application's metadata directly in this packaging org.
    3. In Setup, go to Package Manager (or Packages).
    4. Click New under "Managed Packages".
    5. Provide a Package Name, select a Namespace Prefix (this is crucial and unique), and fill in other details. Click Save.
    6. Add all your developed components to this package.
    7. Click Upload to create a new version of your managed package.

b. 2nd Generation Managed Packages (2GP):

  • Description: 2GP is the modern, source-driven approach to managed packaging built on Salesforce DX. It emphasizes modularity, version control, and a streamlined developer experience. This is the recommended approach for new managed packages.
  • Development Model: Source-driven development. Your metadata is stored in a Git repository, and packages are built directly from this source. Development happens in scratch orgs, which are temporary, disposable Salesforce environments.
  • Advantages over 1GP:
    • Modularity: Supports creating multiple, smaller packages (often called "package modules" or "dependencies"). This allows for better organization and independent development of different parts of your application.
    • Source-Driven: All package definition and development are managed in version control (Git). This aligns with modern DevOps practices.
    • CI/CD Friendly: Integrates seamlessly with CI/CD pipelines for automated builds, testing, and deployments of package versions.
    • Better Developer Experience: Uses scratch orgs for isolated, disposable development environments, reducing conflicts and improving productivity.
    • Dependency Management: Easier to define and manage dependencies between different packages.
  • Creation (SFDX CLI - High-Level Steps):

    2GP creation is primarily done using the Salesforce CLI and requires a Salesforce Dev Hub org enabled.

    1. Enable Dev Hub: In your production or developer org, go to Setup, search for Dev Hub, and enable it. This org will manage your package creation.
    2. Set up SFDX Project: Ensure your Salesforce DX project is set up with your source code in a Git repository. Your sfdx-project.json file is key for package definition.
      # Example sfdx-project.json configuration for a 2GP managed package
      {
        "packageDirectories": [
          {
            "path": "force-app",
            "default": true,
            "package": "MyAwesomeApp",
            "versionName": "ver 1.0",
            "versionNumber": "1.0.0.NEXT",
            "ancestorId": null,
            "definitionFile": "config/project-scratch-def.json"
          }
        ],
        "namespace": "mycompany", // Your unique namespace prefix
        "sfdcLoginUrl": "https://login.salesforce.com",
        "sourceApiVersion": "58.0"
      }
      
    3. Create the Package (in Dev Hub): This command registers your package with the Dev Hub.
      sf package create --name "MyAwesomeApp" --path "force-app" --packagetype Managed --json --target-dev-hub YourDevHubAlias
      # --json: outputs in JSON format
      # --target-dev-hub: specifies your Dev Hub alias
      

      This command returns a Package ID (e.g., 0Ho...). Update your sfdx-project.json with this ID.

    4. Create a Package Version (Build the Package): This command builds a specific version of your package from your source code.
      sf package version create --package "MyAwesomeApp" --installation-key-bypass --wait 10 --json --target-dev-hub YourDevHubAlias
      # --package: uses the package alias defined in sfdx-project.json
      # --installation-key-bypass: allows installation without a key (for testing)
      # --wait 10: waits up to 10 minutes for the version to be created
      

      This command returns a Package Version ID (e.g., 04t...). This is the ID you use to install the package.

    5. Promote the Package Version (Optional, for Release): Once a package version is tested and stable, you promote it to make it generally available for installation.
      sf package version promote --package "04txxxxxxxxxxxxxxxx" --json --target-dev-hub YourDevHubAlias
      # Use the Package Version ID from the previous step.
      

4. Unlocked Packages

Unlocked packages are a type of 2nd Generation package that provides a more flexible way to manage and deploy metadata for internal projects. They are source-driven and version-controlled, but their components are "unlocked" (editable) after installation. They are a modern alternative to Change Sets and the Ant Migration Tool for internal development.

  • Key Characteristics:
    • Source-Driven & Version-Controlled: Like 2GP managed packages, they are built from source in a Git repository, promoting modern development practices.
    • Editable Components: This is the key differentiator. Components are editable after installation in the target org. This flexibility is great for internal teams who might need to make minor adjustments directly in a sandbox.
    • Upgrade Path: Supports upgrades, but changes made in the target org can be overwritten by new package versions. Careful management of local changes is required.
    • No Namespace (Typically): Unlocked packages typically do not have a unique namespace (unless explicitly added for specific reasons). This can lead to naming conflicts if not managed carefully.
    • Internal Use: Primarily designed for internal development teams to modularize and manage their own Salesforce customizations. They are not intended for AppExchange distribution.
    • Deletion: Uninstalling an unlocked package removes the package container and all its components from the target org.
  • Use Cases:
    • Modularizing large enterprise Salesforce implementations into smaller, manageable units.
    • Managing metadata for internal projects with version control and CI/CD.
    • Facilitating agile development and continuous delivery for internal teams.
    • Replacing Change Sets and Ant Migration Tool for complex internal deployments, offering better automation.
    • Distributing common components or base configurations across different internal orgs (e.g., multiple production orgs for different business units).
  • How to Create (SFDX CLI - High-Level Steps):

    Creating unlocked packages is very similar to 2GP managed packages, using the Salesforce CLI and a Dev Hub org.

    1. Enable Dev Hub: Ensure your Salesforce Dev Hub is enabled.
    2. Set up SFDX Project: Configure your sfdx-project.json for an unlocked package.
      # Example sfdx-project.json configuration for an Unlocked package
      {
        "packageDirectories": [
          {
            "path": "force-app",
            "default": true,
            "package": "MyInternalApp",
            "versionName": "ver 1.0",
            "versionNumber": "1.0.0.NEXT",
            "ancestorId": null,
            "definitionFile": "config/project-scratch-def.json"
          }
        ],
        "sfdcLoginUrl": "https://login.salesforce.com",
        "sourceApiVersion": "58.0"
      }
      
    3. Create the Package (in Dev Hub): Register your unlocked package.
      sf package create --name "MyInternalApp" --path "force-app" --packagetype Unlocked --json --target-dev-hub YourDevHubAlias
      # This returns a Package ID (e.g., 0Ho...). Update sfdx-project.json.
      
    4. Create a Package Version (Build the Package): Build a specific version from your source.
      sf package version create --package "MyInternalApp" --wait 10 --json --target-dev-hub YourDevHubAlias
      # This returns a Package Version ID (e.g., 04txxxxxxxx).
      # Note: No --installation-key-bypass needed for unlocked packages by default.
      
    5. Install the Package Version: Install the created package version into any target org (e.g., Sandbox, Production).
      sf package install --package "04txxxxxxxxxxxxxxxx" --target-org mySandboxAlias --wait 10
      # Use the Package Version ID from the previous step.
      

5. Choosing the Right Package Type

The choice of package type depends heavily on your use case, audience, and development methodology.

  • Unmanaged Packages:
    • When to use: Simple code sharing, open-source projects, templates, small one-off deployments where the recipient needs full editability and no future upgrades are expected.
    • When NOT to use: Commercial applications, complex enterprise deployments, situations requiring intellectual property protection, or when you need a clear upgrade path.
  • Managed Packages (2GP preferred for new):
    • When to use: Building applications for the Salesforce AppExchange (ISVs), commercial products, solutions requiring intellectual property protection, and a robust upgrade mechanism.
    • When NOT to use: Internal organizational customizations where full editability in target orgs is desired, or for simple deployments not intended for broad distribution.
  • Unlocked Packages:
    • When to use: Internal enterprise development, modularizing large Salesforce orgs, adopting source-driven development and CI/CD for internal projects, replacing Change Sets for complex deployments, distributing common internal components.
    • When NOT to use: AppExchange products (use Managed Packages), or when you need strict intellectual property protection.

For most internal development, Unlocked Packages combined with Salesforce DX and a robust CI/CD pipeline are the recommended modern approach, as they offer the benefits of version control and automation while retaining flexibility.

6. Conclusion & Key Takeaways

Salesforce packaging is a powerful mechanism for managing and distributing your customizations. Understanding the different package types and their appropriate use cases is crucial for efficient and scalable Salesforce development.

Key Takeaways:

  • Unmanaged Packages: Simple sharing, fully editable, no upgrade path. Best for open-source and templates.
  • Managed Packages: For AppExchange products, intellectual property protection, and controlled upgrades. 2GP is the modern, source-driven approach.
  • Unlocked Packages: For internal enterprise development, modularity, version control, and flexible upgrades. A modern alternative to Change Sets.
  • Salesforce DX & SFDX CLI: Essential tools for modern packaging (2GP and Unlocked Packages), enabling source-driven development and CI/CD.

By leveraging the right packaging strategy, you can streamline your development lifecycle, improve collaboration, and ensure the consistent and reliable deployment of your Salesforce solutions.