| name | Managed Package Architecture |
| description | This skill should be used when the user asks to "design package structure", "create managed package", "configure 2GP", "set up namespace", "version management", or mentions managed package topics like "LMA", "subscriber orgs", or "package versioning". Provides comprehensive guidance for second-generation managed package (2GP) architecture, ISV development patterns, and package lifecycle management. |
| version | 0.1.0 |
Managed Package Architecture
Comprehensive guide for designing and implementing second-generation managed packages (2GP) for ISV applications. Focus on namespace strategy, package structure, versioning, and subscriber org considerations.
Second-Generation Managed Packages Overview
Second-generation managed packages (2GP) combine the benefits of source-driven development with enterprise-grade package management. Use 2GP for:
- ISV applications requiring licensing and protection
- Multi-org distribution to customers (subscriber orgs)
- Intellectual property protection through code obfuscation
- Version management with patch, minor, and major releases
- Dependency management across multiple packages
Key Differences from First-Generation
2GP provides source-driven development (SFDX projects), unlocked package capabilities during development, granular package dependencies, ancestor versioning for patches, and automated package creation via CLI/CI-CD.
Prerequisites
- Dev Hub org enabled (
EnableDevHubpermission) - Namespace registered and linked to Dev Hub
- SFDX project initialized (
sfdx-project.json) - Source-tracked metadata in package directories
- Understanding of semantic versioning (major.minor.patch.build)
Namespace Strategy
Namespace Registration
Register namespaces in the Dev Hub org. Navigate to Setup > Package Manager > Namespace Registry. Choose a unique, descriptive namespace (3-15 characters, alphanumeric). Link the namespace to the Dev Hub org. Namespace selection is permanent and cannot be changed after package release.
Namespace Considerations
Code references: All Apex classes, triggers, objects, and fields require namespace prefixes in subscriber orgs (namespace__ClassName, namespace__Object__c, namespace__Field__c).
Cross-namespace access: Use global keyword for Apex classes/methods accessible to subscriber orgs. Mark components as @AuraEnabled or @InvocableMethod for Lightning/Flow access. Declare explicit dependencies in sfdx-project.json.
Local development: Develop without namespace prefixes in scratch orgs (namespace applied during packaging). Use namespace tokens %NAMESPACE% in references that need runtime resolution. Test with namespace enabled in packaging org to catch reference issues.
Namespace-Free Development Pattern
Configure sfdx-project.json with namespace field but develop locally without prefixes:
{
"namespace": "myapp",
"packageDirectories": [
{
"path": "force-app",
"package": "MyApp Core",
"versionName": "Winter 25",
"versionNumber": "1.2.0.NEXT"
}
]
}
Reference components without namespace during development (MyClass.method()). Package creation automatically applies namespace (myapp__MyClass.method()). Test in packaging org or subscriber org to validate namespaced references.
Package Directory Structure
Single Package Layout
Structure for single managed package:
force-app/ # Package directory
├── main/
│ ├── default/
│ │ ├── classes/ # Apex classes
│ │ ├── triggers/ # Apex triggers
│ │ ├── objects/ # Custom objects
│ │ ├── flows/ # Flows
│ │ ├── lwc/ # Lightning Web Components
│ │ └── ... # Other metadata
sfdx-project.json # Package configuration
Multi-Package Layout (Modular Architecture)
Structure for multiple related packages with dependencies:
core/ # Core package (foundation)
├── main/default/
│ ├── classes/
│ ├── objects/
extensions/ # Extension package (depends on core)
├── main/default/
│ ├── classes/
│ ├── flows/
integrations/ # Integration package (depends on core)
├── main/default/
│ ├── classes/
sfdx-project.json # Defines all packages + dependencies
Configure sfdx-project.json with package dependency tree:
{
"packageDirectories": [
{
"path": "core",
"package": "MyApp Core",
"versionNumber": "1.0.0.NEXT",
"default": true
},
{
"path": "extensions",
"package": "MyApp Extensions",
"versionNumber": "1.0.0.NEXT",
"dependencies": [
{
"package": "MyApp Core",
"versionNumber": "1.0.0.LATEST"
}
]
}
]
}
Directory Organization Best Practices
Group by feature: Organize metadata by business capability (e.g., sales/, service/, analytics/).
Separate configuration: Keep subscriber-configurable metadata (custom settings, custom metadata types) in dedicated directories.
Version control: Use .forceignore to exclude non-package metadata (user records, org preferences).
Testing strategy: Place test classes in tests/ subdirectory or use @IsTest annotation for automatic exclusion from packages.
Package Configuration (sfdx-project.json)
Essential Fields
namespace: Registered namespace linked to Dev Hub.
packageDirectories: Array of package definitions with path (directory), package (name), versionNumber (major.minor.patch.NEXT/LATEST), versionName (release label), dependencies (required packages).
packageAliases: Human-readable aliases mapped to package IDs (0Ho) and version IDs (04t).
Version Number Format
Use semantic versioning: major.minor.patch.build
- Major: Breaking changes, incompatible API changes
- Minor: New features, backward-compatible additions
- Patch: Bug fixes, backward-compatible fixes
- Build: Auto-incremented by Salesforce (use NEXT for next build)
Dependency Specification
Declare dependencies with explicit version ranges:
"dependencies": [
{
"package": "MyApp Core@1.2.0-5",
"versionNumber": "1.2.0.LATEST"
},
{
"package": "External Library",
"versionNumber": "2.0.0.5"
}
]
Use LATEST for latest released version of major.minor.patch. Use specific build numbers for pinned dependencies. Order dependencies hierarchically (foundation packages first).
Package Creation Workflow
Initial Package Creation
Create package in Dev Hub:
sf package create \
--name "MyApp Core" \
--package-type Managed \
--path force-app \
--description "Core functionality for MyApp" \
--target-dev-hub devhub
This generates package ID (0Ho) and updates packageAliases in sfdx-project.json.
Version Creation
Create package version from source:
sf package version create \
--package "MyApp Core" \
--installation-key-bypass \
--wait 30 \
--code-coverage \
--target-dev-hub devhub
Add --installation-key <password> for protected installations. Use --code-coverage to enforce 75% Apex coverage requirement. Wait time allows for Apex test execution (increase for large packages).
Monitor version creation:
sf package version create report --package-create-request-id 08c...
Version Promotion
Promote beta version to released:
sf package version promote \
--package "MyApp Core@1.0.0-1" \
--target-dev-hub devhub
Critical: Promotion is irreversible. Released versions cannot be deleted or modified. Validate thoroughly in beta before promotion. Ensure Apex coverage meets 75% threshold. Test upgrade paths from previous versions.
Version Management and Upgrade Strategies
Semantic Versioning Strategy
Major versions (2.0.0): Breaking changes requiring subscriber action. Deprecated API removal. Database schema changes affecting existing data. UI/UX redesigns impacting user workflows.
Minor versions (1.1.0): New features, backward-compatible. New Apex methods (mark old as deprecated). Additional fields on existing objects. New Lightning components.
Patch versions (1.0.1): Critical bug fixes. Security patches. Performance improvements. Documentation updates.
Ancestor Versioning
Create patches based on previous released versions:
sf package version create \
--package "MyApp Core" \
--version-number 1.0.1.NEXT \
--ancestor 1.0.0-8 \
--target-dev-hub devhub
Use cases: Patch critical bugs in production while developing next minor/major version. Maintain multiple release branches (LTS support). Provide subscriber-specific fixes without forcing latest version.
Deprecation Pattern
Mark components for future removal:
/**
* @deprecated Use NewClass.newMethod() instead. Will be removed in version 3.0.0.
*/
@Deprecated
global static void oldMethod() {
// Implementation
}
Document deprecation timeline in release notes. Maintain deprecated code for at least one major version. Provide migration guides and automated refactoring tools.
Upgrade Testing
Test upgrade paths between versions:
- Install previous version in test org
- Add representative data and configurations
- Install new version (upgrade simulation)
- Validate data integrity and functionality
- Test rollback scenarios (uninstall/reinstall previous version)
Use scratch orgs with org snapshots for repeatable testing.
ISV Considerations
License Management Application (LMA)
Install LMA in production org (not Dev Hub). Configure license definitions (trial, standard, enterprise). Track subscriber org installations and licenses. Monitor usage metrics and API calls from subscriber orgs. Automate license provisioning via API.
See: references/isv-considerations.md for LMA setup and subscriber org patterns.
Subscriber Org Compatibility
API version compatibility: Test against minimum supported API version. Use @since annotations to document version requirements.
Governor limits: Design for multi-tenant limits (200 SOQL queries, 10 MB heap). Implement bulkification patterns for batch operations. Provide subscriber configuration for governor-intensive features.
Edition requirements: Specify minimum Salesforce edition (Professional, Enterprise, Unlimited). Document required features (Platform Encryption, Change Data Capture).
Sandbox testing: Test installation in Developer, Partial, Full sandbox types. Validate metadata deployment patterns for subscriber CI/CD.
Protected Components
Use global sparingly. Expose only necessary APIs to subscribers. Mark classes public for internal package use (not accessible to subscribers). Use @TestVisible for test-only access. Implement managed interfaces (global interface) for extensibility.
Package Security
Enable Security Review requirements for AppExchange. Implement CRUD/FLS checks (Security.stripInaccessible()). Use with sharing for all subscriber-facing Apex. Sanitize user inputs to prevent SOQL/XSS injection. Encrypt sensitive data using Platform Encryption or Shield.
Installation and Distribution
Installation Methods
Salesforce CLI:
sf package install \
--package 04t... \
--target-org subscriber-org \
--wait 20
Installation URL:
https://login.salesforce.com/packaging/installPackage.apexp?p0=04t...
AppExchange: Publish to AppExchange for automated discovery and installation. Requires security review and listing approval.
Post-Install Configuration
Provide post-install scripts (Apex class implementing InstallHandler):
global class PostInstallHandler implements InstallHandler {
global void onInstall(InstallContext context) {
// Configure default settings
// Create sample data
// Send confirmation email
}
}
Include setup guides for subscriber admins (permission sets, custom settings, remote site settings).
Uninstall Considerations
Clean up custom settings and custom metadata on uninstall. Document data retention policies (deleted objects, archived records). Prevent uninstall if dependencies exist (use @Deprecated warnings).
Testing Strategy
Apex Code Coverage
Achieve minimum 75% coverage for package promotion. Write unit tests for all global/public methods. Test subscriber org scenarios (different editions, data volumes). Use @IsTest(SeeAllData=false) for isolated tests.
Integration Testing
Test package with common subscriber configurations (communities, Experience Cloud, integrations). Validate multi-package installations (dependency resolution). Test upgrade paths (version N-1 to N, N-2 to N). Simulate subscriber customizations (custom fields, triggers, validation rules).
Performance Testing
Load test with production-scale data volumes. Profile SOQL query counts and heap usage. Test concurrent user scenarios (50+ users). Monitor LMA metrics for subscriber org performance.
Continuous Integration/Deployment
CI/CD Pipeline Pattern
- Source commit: Developer pushes to version control (GitHub, GitLab)
- Validation: Run Apex tests, validate package creation
- Beta version: Create beta package version automatically
- Integration testing: Install in test org, run integration tests
- Manual approval: Review test results, approve promotion
- Promotion: Promote to released version
- Distribution: Update installation links, notify subscribers
Automation Tools
Use GitHub Actions, GitLab CI, or Jenkins for pipeline automation. Leverage sf package version create --json for programmatic version creation. Store Dev Hub auth token securely (encrypted secrets). Tag releases in version control matching package versions.
Common Pitfalls and Solutions
Namespace conflicts: Test with namespace enabled early in development cycle.
Dependency loops: Design package hierarchy without circular dependencies.
Metadata exclusions: Use .forceignore to prevent non-package metadata inclusion.
Coverage failures: Run tests locally before package version creation (sf apex run test).
Breaking changes: Use deprecation workflow instead of immediate removal.
Installation failures: Validate against subscriber org types (sandboxes, production, Developer Edition).
Performance degradation: Profile package in subscriber org context (governor limits apply differently).
Quick Reference
Create package: sf package create --name "MyApp" --package-type Managed --path force-app
Create version: sf package version create --package "MyApp" --wait 30 --code-coverage
Promote version: sf package version promote --package "MyApp@1.0.0-1"
Install package: sf package install --package 04t... --target-org subscriber-org
List versions: sf package version list --package "MyApp"
Detailed configuration examples: See references/package-structure-examples.md
ISV patterns and LMA setup: See references/isv-considerations.md
Additional Resources
- Salesforce 2GP Developer Guide: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_dev2gp.htm
- Package Development Model: https://trailhead.salesforce.com/content/learn/modules/sfdx_dev_model
- ISV Guide: https://developer.salesforce.com/docs/atlas.en-us.packagingGuide.meta/packagingGuide/