Building a managed package starts in a Dev Hub with Salesforce DX. You scaffold the project, write the metadata in source format, declare the package in sfdx-project.json, build a version, and submit for security review before publishing on AppExchange.
- Register the namespace
Open the Dev Hub org, Setup, Packages, Edit. Enter your chosen namespace (1 to 15 characters, no spaces). The namespace is registered with Salesforce and cannot be transferred. Pick deliberately.
- Scaffold the DX project
sf project generate creates the folder structure. Edit sfdx-project.json to add a packageDirectories entry with package: MyApp, versionName: 1.0, versionNumber: 1.0.0.NEXT.
- Create the package
sf package create --name MyApp --description "My App description" --package-type Managed creates the package metadata in the Dev Hub. The Salesforce package ID (starting with 0Ho) is registered against the namespace.
- Build the package version
sf package version create --package MyApp --installation-key-bypass --code-coverage builds a version from the current source. The CLI runs all Apex tests, validates coverage, packages the metadata, and outputs an install URL (starts with /packaging/installPackage.apexp).
- Test installs in a scratch org
sf package install --package <version-id> --target-org testscratch installs the package into a scratch org. Verify the metadata appears, the Apex tests pass, and the install profile flows work.
- Submit for Security Review
Open the Partner Portal, AppExchange Submission, and submit the package version for Security Review. Provide the install URL, test org credentials, test data, and the security checklist. Wait 4 to 8 weeks for initial review.
- Publish the listing on AppExchange
Once security review approves, publish the listing on AppExchange with screenshots, demo videos, pricing, and review intake. The package is live and installable by customers.
Permanent 1-15 char identifier registered with Salesforce. Every component in the package carries this prefix. Cannot be transferred or unregistered.
Managed or Unlocked. Managed packages have namespace lock and code protection. Unlocked packages are for internal modularization, not AppExchange.
global, public, private modifiers on Apex classes and methods. Global is the public API; public is package-internal; private is class-local.
Managed, Deletable, Required Feature. Determines what the package can change in future versions. A permanent decision per component.
ISV-initiated auto-upgrade to subscriber orgs. Available for minor and patch versions. Customers can subscribe to push notifications but not opt out individually.
Managed package the ISV installs in their License Management Org to track package licenses, renewals, and seat counts across all subscribers.
- Namespace prefixes are permanent. Picking a poor name early creates a permanent eyesore on every component. Spend a week choosing before registering.
- Global Apex is a permanent API commitment. Once a method is global and shipped, you cannot rename it, change its signature, or remove it without breaking subscriber code.
- Managed components cannot be modified in the subscriber org. Customers who need to extend a managed package must use the extension points (custom metadata, callbacks) the ISV exposed. Add these intentionally during design.
- Security Review is mandatory before publishing on AppExchange. Plan 4 to 8 weeks for the initial review and 2 to 4 weeks for each major version. Build the timeline into the release plan.
- Push Upgrades are silent to subscribers unless the ISV opts in to notification. Communicate breaking changes to customers proactively even when the upgrade is technically backwards-compatible.