Salesforce provides multiple packaging mechanisms for distributing metadata and code across organizations. Choosing the right package type depends on your distribution goals, intellectual property requirements, and organizational structure. This analysis examines five primary package types and provides recommendations for enterprise code distribution.
Package Types Overview
1. Unmanaged Packages
Unmanaged packages are collections of application components that can be distributed and installed in other Salesforce orgs. Once installed, the components become editable by administrators and developers in the target org.
Characteristics
| Feature | Description |
|---|---|
| Editability | Fully editable after installation |
| Upgradeability | No upgrade path – one-time deployment only |
| IP Protection | None – all code is visible and modifiable |
| Namespace | Not required |
| Use Case | Open-source distribution, templates, one-time transfers |
Pros
- Simple to create and distribute
- Recipients can fully customize the code
- No ongoing maintenance required from publisher
- No namespace prefix added to components
- Good for sharing templates and starter code
Cons
- No version control or upgrade capability
- No intellectual property protection
- Changes must be manually tracked
- Cannot push updates to installed orgs
- No way to recall or enforce standards
Best Use Cases
- Distributing open-source projects to developers
- One-time deployment of applications requiring customization
- Sharing code templates or starter kits
- Internal proof-of-concept transfers
2. Managed Packages (First-Generation – 1GP)
First-generation managed packages are the traditional method for ISVs to distribute applications on AppExchange. They provide intellectual property protection and version management.
Characteristics
| Feature | Description |
|---|---|
| Editability | Limited – subscribers cannot modify protected components |
| Upgradeability | Push upgrades available to subscribers |
| IP Protection | Full Apex obfuscation and component locking |
| Namespace | Required (unique per package) |
| Development Model | Org-based (packaging org is source of truth) |
Pros
- Full intellectual property protection
- Automatic code obfuscation for Apex
- Version management and upgrade paths
- License management capabilities
- AppExchange distribution ready
- Push upgrades to subscriber orgs
Cons
- Org-based development model limits collaboration
- Each package requires unique namespace, causing proliferation of global Apex
- Managing hundreds of packaging orgs becomes complex
- Difficult to adopt modern CI/CD practices
- Monolithic architecture encouraged
- Limited code sharing between packages
When to Use
- Legacy AppExchange applications
- When specific metadata types only support 1GP
- When dependent packages must be 1GP
3. Second-Generation Managed Packages (2GP)
Second-generation managed packages represent the modern approach to ISV development, combining intellectual property protection with source-driven development practices.
Characteristics
| Feature | Description |
|---|---|
| Editability | Limited – same protection as 1GP |
| Upgradeability | Version and patch upgrades supported |
| IP Protection | Full Apex obfuscation |
| Namespace | Multiple packages can share same namespace |
| Development Model | Source-driven (version control is source of truth) |
| Code Coverage | Minimum 75% required for release |
Key Advantages Over 1GP

Pros
- Source-driven development with version control as source of truth
- Multiple packages can share a single namespace
- Single Dev Hub org manages all packages
- Full CI/CD integration capability
- Modular package architecture
- @namespaceAccessible annotation for code sharing
- Package Migrations feature for 1GP conversion
Cons
- 75% code coverage required for release
- Learning curve for source-driven development
- Requires Dev Hub org setup
- Some metadata types may not be supported yet
Namespace Sharing Example
With 2GP, you can share Apex code across packages using the @namespaceAccessible annotation:
@namespaceAccessible
public class SharedUtility {
@namespaceAccessible
public static String formatCurrency(Decimal amount) {
return '$' + amount.format();
}
}
4. Unlocked Packages
Unlocked packages are designed for enterprise customers and internal development teams. They provide the benefits of modular development without the restrictions of managed packages.
Characteristics
| Feature | Description |
|---|---|
| Editability | Administrators can modify installed components |
| Upgradeability | Full version and upgrade support |
| IP Protection | None – code is visible |
| Namespace | Optional (recommended for multiple teams) |
| Code Coverage | 75% required for promotion to released |
Pros
- Ideal for internal business applications
- Modular development with dependency management
- Version control integration
- Repeatable, scriptable deployments
- Administrators can still modify metadata after installation
- Supports modern DevOps practices
- Team-based ownership of packages
Cons
- No intellectual property protection
- Not suitable for AppExchange distribution
- 75% code coverage for released versions
- Package version creation has daily limits
- ~8 minute wait for package version creation
Modular Architecture Benefits

5. Org-Dependent Unlocked Packages
Org-dependent unlocked packages are a specialized variant designed for complex, legacy Salesforce orgs that have accumulated tightly coupled metadata over years.
Characteristics
| Feature | Description |
|---|---|
| Dependencies | Can depend on unpackaged metadata in target org |
| Migration Path | Incremental modernization of legacy orgs |
| Flexibility | Higher than standard unlocked packages |
Pros
- Perfect for legacy orgs with complex dependencies
- Incremental path to modular architecture
- No need to package all dependencies upfront
- Reduces refactoring effort for existing orgs
Cons
- Can only be installed in specific org configurations
- Less portable than standard unlocked packages
- May perpetuate technical debt if overused
Comparison Matrix
| Feature | Unmanaged | Managed 1GP | Managed 2GP | Unlocked | Org-Dependent |
|---|---|---|---|---|---|
| IP Protection | None | Full | Full | None | None |
| Upgradeable | No | Yes | Yes | Yes | Yes |
| Subscriber Editable | Yes | Limited | Limited | Yes | Yes |
| AppExchange Ready | No | Yes | Yes | No | No |
| Namespace Required | No | Yes | Yes | Optional | Optional |
| Source-Driven Dev | N/A | No | Yes | Yes | Yes |
| CI/CD Integration | Limited | Poor | Excellent | Excellent | Excellent |
| Modular Architecture | No | Poor | Yes | Yes | Yes |
| Code Coverage Req. | None | 75% | 75% | 75%* | 75%* |
| License Management | No | Yes | Yes | No | No |
*For released versions only
Decision Framework: Which Package Type to Use?

Quick Reference Guide
| Scenario | Recommended Package |
|---|---|
| Internal enterprise app development | Unlocked Package |
| AppExchange ISV with modern practices | Managed 2GP |
| Legacy AppExchange app maintenance | Managed 1GP or migrate to 2GP |
| Sharing open-source code/templates | Unmanaged Package |
| Modernizing complex legacy org | Org-Dependent Unlocked |
| Distributing IP-protected code internally | Consider Managed 2GP (yes, even internal) |
Best Practices for Distributing Common Code in an Organization
Strategy 1: Modular Unlocked Package Architecture
For most enterprises, the recommended approach is a layered unlocked package architecture:

Strategy 2: Team-Based Package Ownership
Assign teams to own specific packages for better accountability:
| Team | Package | Responsibilities |
|---|---|---|
| Platform Team | Core Utilities | Shared libraries, security |
| Data Team | Data Model | Objects, fields, relationships |
| Integration Team | Integration Package | APIs, MuleSoft connectors |
| Sales Dev Team | Sales App | Sales-specific features |
| Service Dev Team | Service App | Case management features |
Strategy 3: Namespace Considerations
Without Namespace: – Simpler for single-team organizations – Easier metadata references – No prefix on API names
With Namespace: – Recommended for multi-team environments – Clear ownership boundaries – Prevents naming conflicts – Required if you might distribute externally later
Strategy 4: Version Control Structure
salesforce-packages/
├── sfdx-project.json
├── packages/
│ ├── core-utilities/
│ │ ├── main/default/
│ │ │ ├── classes/
│ │ │ ├── triggers/
│ │ │ └── objects/
│ │ └── test/default/
│ ├── data-model/
│ ├── sales-app/
│ └── service-app/
├── scripts/
│ ├── create-scratch-org.sh
│ └── deploy-packages.sh
└── .github/
└── workflows/
└── ci-cd.yml
Implementation Roadmap
Want to master Salesforce DX and packaging? Check out my Salesforce DX course on Udemy for hands-on training covering scratch orgs, unlocked packages, CI/CD pipelines, and more.
Phase 1: Assessment
- Analyze existing metadata – Catalog all components
- Identify package boundaries – Group related functionality
Phase 2: Setup
- Enable Dev Hub in your production org
- Define namespace (if using)
- Create package structure in sfdx-project.json
- Establish CI/CD pipelines
Phase 3: Development
- Start with core package containing shared utilities
- Add dependent packages incrementally
- Implement automated testing
- Validate in scratch orgs
Phase 4: Deployment
- Deploy to sandbox for UAT
- Promote packages to released status
- Install in production
- Monitor and iterate
Package Dependencies and Architecture
Dependency Declaration
In sfdx-project.json:
{
"packageDirectories": [
{
"path": "packages/core-utilities",
"package": "Core Utilities",
"versionName": "Winter '26",
"versionNumber": "1.0.0.NEXT"
},
{
"path": "packages/sales-app",
"package": "Sales App",
"versionName": "Winter '26",
"versionNumber": "1.0.0.NEXT",
"dependencies": [
{
"package": "Core Utilities",
"versionNumber": "1.0.0.LATEST"
}
]
}
],
"namespace": "mycompany"
}
Dependency Rules
| Package Type | Can Depend On |
|---|---|
| Unlocked | Unlocked, Managed 1GP, Managed 2GP |
| Managed 2GP | Managed 1GP, Managed 2GP (same namespace) |
| Managed 1GP | Managed 1GP only |
Avoiding Circular Dependencies
- Design clear hierarchical layers
- Core/utility packages at the bottom
- Application packages at the top
- Use interfaces to decouple when needed
Common Pitfalls and Solutions
Pitfall 1: Monolithic Package Syndrome
Problem: Creating one large package with all metadata
Solution: Break into smaller, focused packages with clear responsibilities
Pitfall 2: Ignoring Code Coverage
Problem: Failing to maintain 75% code coverage
Solution: Include tests in packages, run coverage on every build
Pitfall 3: Over-Engineering Dependencies
Problem: Creating too many small packages with complex dependency chains
Solution: Balance modularity with practical maintainability
Pitfall 4: No Namespace Strategy
Problem: Conflicts when multiple teams develop independently
Solution: Use namespace for multi-team environments
Pitfall 5: Skipping Scratch Org Testing
Problem: Packages work in sandboxes but fail in fresh orgs
Solution: Always validate packages in scratch orgs first
Recommendations
For Enterprise Internal Development
Primary Choice: Unlocked Packages
- Start with a core utilities package containing shared code
- Create functional packages for major business areas
- Use org-dependent packages for legacy transitions
- Implement CI/CD with automated testing
- Consider namespace for large multi-team organizations
For ISVs and AppExchange Partners
Primary Choice: Managed 2GP
- Adopt source-driven development from the start
- Use namespace sharing for modular products
- Leverage @namespaceAccessible for code sharing
- Plan for Package Migrations if converting from 1GP
- Maintain 75% code coverage continuously
For One-Time Code Sharing
Primary Choice: Unmanaged Packages
- Use for templates and starter kits
- Document clearly what customization is expected
- Consider providing as open-source on GitHub alongside
Key Findings
- Unlocked Packages are the recommended choice for internal enterprise development
- Managed 2GP packages are ideal for AppExchange distribution with modern DevOps practices
- Unmanaged Packages are suitable only for one-time code transfers
- Modular architecture with package dependencies enables scalable enterprise development
Have questions about Salesforce packaging options? Drop a comment below!

Leave a Reply