← All posts
· 3 min read ·
SalesforceSalesforce CLIDevOpsArchitecture

From Org-Based to Package-Based Development: A Practical Migration Guide

Package-based development is the future of Salesforce development - but migrating from an org-based model is non-trivial. Here's a realistic path through it.

Code on a monitor showing package development

Package-based development (PBD) in Salesforce is one of those things that sounds straightforward in Salesforce documentation and is genuinely complex in practice. The org you’re migrating from has 8 years of accumulated metadata, circular dependencies between components you didn’t know existed, and custom code that references managed package fields in ways that aren’t obvious until you try to extract them.

This is a realistic guide - not the happy path.

Why Bother

The advantages of unlocked packages over org-based development are real:

  • Dependency management - packages explicitly declare what they depend on
  • Versionable - you can deploy a specific version, roll back to a previous one
  • Testable in isolation - package tests run against only their dependencies, not the entire org
  • Faster CI - test a package in a scratch org in 8 minutes vs deploying an entire org’s metadata in 30

For teams managing large codebases with multiple teams, the investment pays back quickly.

Step 1: Dependency Mapping Before You Write Any CLI Commands

Before you touch sfdx-project.json, spend time understanding your current org’s component dependency graph. Salesforce provides this via the Metadata API and tooling:

sf data query \
  --query "SELECT MetadataComponentId, MetadataComponentName, MetadataComponentType, RefMetadataComponentName, RefMetadataComponentType FROM MetadataComponentDependency" \
  --use-tooling-api \
  --result-format csv > dependencies.csv

Visualise this. You will find unexpected cycles. Resolve those first, or your package decomposition will inherit them.

Step 2: Identify Natural Package Boundaries

Look for clusters of components that change together and are used together. Common boundaries for a Commerce Cloud / Sales Cloud org:

  • Core - shared utilities, base objects, foundation classes
  • Commerce - Commerce Cloud integration, order management
  • CRM - Sales and Service Cloud customisations
  • Integration - External service callouts, Platform Events, API layer

The anti-pattern is too many tiny packages. I’ve seen orgs decompose into 40 packages and spend more time managing package versions than writing features.

Step 3: Start With a New Package, Not a Migration

The most pragmatic path is not to migrate your existing metadata - it’s to start writing new features as packages while the legacy org-based code stays as-is temporarily.

New feature required? Build it as an unlocked package. Existing code touched as part of that feature? Gradually migrate the touched components into the appropriate package.

This avoids the “big bang” migration that stalls for months.

Step 4: Scratch Org Shapes

Package development requires scratch orgs, and scratch orgs need to match your target org’s shape. Get your scratch org definition right early:

{
  "orgName": "Development Scratch Org",
  "edition": "Enterprise",
  "features": ["Communities", "EventMonitoring", "ServiceCloud"],
  "settings": {
    "lightningExperienceSettings": { "enableS1DesktopEnabled": true },
    "mobileSettings": { "enableS1EncryptedStoragePref2": false }
  }
}

Scratch org creation failures due to missing features or settings are a major source of pipeline friction. Invest time here.

Step 5: Managing Managed Package Dependencies

If your org has managed package dependencies (and every real org does), you need to specify them in your package dependency tree. This is where things get complicated - you can’t easily test managed package interactions in scratch orgs without a full setup.

Use a Developer Hub with pre-configured namespaces for packages that require org-specific setup.

The Honest Timeline

A realistic migration for a mature org with 500+ metadata components:

  • Months 1-2 - Dependency analysis, package boundary design, scratch org setup, first new feature as a package
  • Months 3-6 - Core package extraction, resolving circular dependencies, CI pipeline updates
  • Months 6-12 - Gradual migration of existing components, team training
  • Year 2 - Legacy org-based code fully migrated (maybe)

Anyone promising a faster timeline is either working on a small org or hasn’t done it before. The investment is worth it for organisations planning to scale - but go in with realistic expectations.

← All posts