multi-package-development

Designing, orchestrating, and maintaining multi-package architectures in Salesforce DX: dependency DAG design, layered package decomposition, install ordering, cross-package API contracts, mono-repo vs. multi-repo layout, and CI/CD pipeline sequencing for projects with two or more unlocked or managed packages. NOT for single-package creation or versioning (see unlocked-package-development), 2GP managed-package ISV workflows (see second-generation-managed-packages), or change-set deployments.

Best use case

multi-package-development is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Designing, orchestrating, and maintaining multi-package architectures in Salesforce DX: dependency DAG design, layered package decomposition, install ordering, cross-package API contracts, mono-repo vs. multi-repo layout, and CI/CD pipeline sequencing for projects with two or more unlocked or managed packages. NOT for single-package creation or versioning (see unlocked-package-development), 2GP managed-package ISV workflows (see second-generation-managed-packages), or change-set deployments.

Teams using multi-package-development should expect a more consistent output, faster repeated execution, less prompt rewriting, better workflow continuity with your supporting tools.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.
  • You already have the supporting tools or dependencies needed by this skill.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/multi-package-development/SKILL.md --create-dirs "https://raw.githubusercontent.com/PranavNagrecha/AwesomeSalesforceSkills/main/skills/devops/multi-package-development/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/multi-package-development/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How multi-package-development Compares

Feature / Agentmulti-package-developmentStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Designing, orchestrating, and maintaining multi-package architectures in Salesforce DX: dependency DAG design, layered package decomposition, install ordering, cross-package API contracts, mono-repo vs. multi-repo layout, and CI/CD pipeline sequencing for projects with two or more unlocked or managed packages. NOT for single-package creation or versioning (see unlocked-package-development), 2GP managed-package ISV workflows (see second-generation-managed-packages), or change-set deployments.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Multi-Package Development

This skill activates when a Salesforce project spans two or more packages (unlocked or managed) and the practitioner needs to design, build, install, or maintain the cross-package dependency graph. It covers package decomposition strategy, dependency DAG design, topological install ordering, sfdx-project.json multi-directory configuration, mono-repo vs. multi-repo layout, and CI/CD pipeline sequencing. It does not cover single-package creation, versioning, or 2GP ISV workflows.

---

## Before Starting

Gather this context before working on anything in this domain:

- How many packages exist today, and what metadata does each contain? Review the `packageDirectories` array in `sfdx-project.json` and the `packageAliases` map.
- What is the current dependency graph? Each package directory's `dependencies` array declares subscriber package version IDs (04t...) it depends on. Circular dependencies are illegal and will cause version-create failures.
- Is the project in a mono-repo (all packages in one repository) or multi-repo (separate repos per package)? This drives CI/CD sequencing and source-of-truth decisions.
- Are packages unlocked, managed, or a mix? Managed packages introduce namespace isolation and @namespaceAccessible constraints that affect cross-package API surfaces.

---

## Core Concepts

### Dependency DAG (Directed Acyclic Graph)

Every multi-package project has a dependency graph. Salesforce enforces that this graph must be acyclic: if Package A depends on Package B, Package B cannot depend on Package A at any depth. The `sf package version create` command resolves dependencies at build time using the subscriber package version IDs listed in `sfdx-project.json`. If a dependency version does not exist or has not been promoted, the build fails.

The DAG determines:
- **Build order** — packages must be versioned from leaves (no dependencies) to root (depends on everything).
- **Install order** — packages must be installed in the same leaf-to-root order in every target org.
- **Upgrade order** — when updating packages, dependents must be upgraded after their dependencies.

### Layered Package Architecture

The standard decomposition pattern is a layered model:

1. **Base/Core layer** — shared objects, fields, and platform utilities with no outbound dependencies.
2. **Domain layer(s)** — business-logic packages (Sales, Service, etc.) that depend on Base.
3. **Experience/UI layer** — LWC, Aura, Flows, and page layouts that depend on Domain and Base.

Each layer depends only on layers below it. This prevents circular references and keeps the base package stable.

### sfdx-project.json Multi-Package Configuration

A single `sfdx-project.json` can declare multiple packages via the `packageDirectories` array. Each entry specifies:
- `path` — the source directory for that package's metadata.
- `package` — the package alias (must match a key in `packageAliases`).
- `versionName` / `versionNumber` — human-readable version label and MAJOR.MINOR.PATCH.BUILD format.
- `dependencies` — array of `{ "package": "<alias>", "versionNumber": "X.Y.Z.LATEST" }` objects declaring upstream packages.
- `default` — at most one directory can be `true`; the CLI uses this when no `--path` is specified.

Only one entry should have `"default": true`. The `packageAliases` section maps human-readable names to subscriber package version IDs (04t...) or package IDs (0Ho...).

### Install Ordering and Idempotency

Packages must be installed in topological order. Installing a package before its dependencies are present in the target org produces `MISSING_DEPENDENCY` errors. In CI/CD, this means the pipeline must:
1. Compute the topological sort of the DAG.
2. Install (or upgrade) each package in that order.
3. Handle partial failures gracefully — a failed mid-chain install should not leave the org in an inconsistent state.

The `sf package install` command is idempotent for the same version: re-installing an already-installed version is a no-op.

---

## Common Patterns

### Pattern 1: Layered Mono-Repo with Shared sfdx-project.json

**When to use:** Teams that own all packages and want a single source of truth for the dependency graph.

**How it works:**

```
my-project/
  sfdx-project.json
  force-app-base/     # Base package source
  force-app-sales/    # Sales domain package source
  force-app-service/  # Service domain package source
  force-app-ui/       # Experience layer source
```

```json
{
  "packageDirectories": [
    {
      "path": "force-app-base",
      "default": true,
      "package": "MyOrg-Base",
      "versionName": "Spring 2025",
      "versionNumber": "1.2.0.NEXT",
      "dependencies": []
    },
    {
      "path": "force-app-sales",
      "package": "MyOrg-Sales",
      "versionName": "Spring 2025",
      "versionNumber": "1.1.0.NEXT",
      "dependencies": [
        { "package": "MyOrg-Base", "versionNumber": "1.2.0.LATEST" }
      ]
    },
    {
      "path": "force-app-ui",
      "package": "MyOrg-UI",
      "versionName": "Spring 2025",
      "versionNumber": "1.0.0.NEXT",
      "dependencies": [
        { "package": "MyOrg-Base", "versionNumber": "1.2.0.LATEST" },
        { "package": "MyOrg-Sales", "versionNumber": "1.1.0.LATEST" }
      ]
    }
  ],
  "packageAliases": {
    "MyOrg-Base": "0HoXXXXXXXXXXXXX",
    "MyOrg-Base@1.2.0-1": "04tXXXXXXXXXXXXX",
    "MyOrg-Sales": "0HoYYYYYYYYYYYYY",
    "MyOrg-Sales@1.1.0-1": "04tYYYYYYYYYYYYY",
    "MyOrg-UI": "0HoZZZZZZZZZZZZZ"
  }
}
```

**Why not the alternative:** Multi-repo setups require cross-repo version pinning and artifact passing between pipelines, adding significant coordination overhead. Mono-repo keeps the DAG visible in one file.

### Pattern 2: Multi-Repo with Pinned Dependencies

**When to use:** Separate teams own separate packages and release on independent cadences, or packages span different Dev Hubs (e.g., ISV + customer).

**How it works:**

Each repo has its own `sfdx-project.json` with a single `packageDirectories` entry. Dependencies reference promoted subscriber package version IDs (04t...) directly:

```json
{
  "packageDirectories": [
    {
      "path": "force-app",
      "default": true,
      "package": "TeamB-Service",
      "versionNumber": "2.0.0.NEXT",
      "dependencies": [
        { "package": "TeamA-Base@1.5.0-3", "versionNumber": "1.5.0.LATEST" }
      ]
    }
  ],
  "packageAliases": {
    "TeamA-Base@1.5.0-3": "04tAAAAAAAAAAAAAAA",
    "TeamB-Service": "0HoBBBBBBBBBBBBB"
  }
}
```

A CI/CD "orchestrator" pipeline (in the consuming repo or a dedicated ops repo) runs after upstream packages publish new versions, updating the pinned 04t IDs and triggering downstream builds.

**Why not the alternative:** In a mono-repo, independent release cadences create merge conflicts in the shared `sfdx-project.json` and force all teams to coordinate releases.

### Pattern 3: Unpackaged Metadata Alongside Packages

**When to use:** Some metadata (profiles, permission sets, org-wide settings) cannot be packaged or must be deployed org-specifically.

**How it works:**

Add an unpackaged directory to `sfdx-project.json` without a `package` key:

```json
{
  "path": "force-app-unpackaged",
  "default": false
}
```

This directory is deployed via `sf project deploy start` after all packages are installed. It is not version-controlled by the packaging system.

**Why not the alternative:** Forcing unpackageable metadata into a package causes version-create failures or installs metadata that should vary per org (e.g., org-specific profiles).

---

## Decision Guidance

| Situation | Recommended Approach | Reason |
|---|---|---|
| Single team, shared release cadence, < 5 packages | Mono-repo with layered directories | One sfdx-project.json is the single source of truth; simpler CI/CD |
| Multiple teams with independent release schedules | Multi-repo with pinned 04t IDs | Avoids cross-team merge conflicts and forced coordinated releases |
| Some metadata is org-specific (profiles, settings) | Unpackaged directory deployed after packages | Keeps packages portable; org-specific config stays outside packages |
| Shared custom objects used by multiple domain packages | Extract into a Base/Core package at the bottom of the DAG | Prevents duplication; all domain packages reference one source of truth |
| Package A and Package B need to reference each other's objects | Refactor shared objects into a new Base package both depend on | Circular dependencies are illegal; extract the shared surface into a lower layer |
| ISV managed package + customer customization packages | Multi-repo; customer packages depend on the managed package's 04t ID | ISV and customer have separate Dev Hubs and release cycles |

---

## Recommended Workflow

Step-by-step instructions for an AI agent or practitioner working on multi-package architecture:

1. **Map the current state** — Parse `sfdx-project.json` and list all `packageDirectories`, their `dependencies`, and the `packageAliases` map. Draw the dependency DAG.
2. **Validate the DAG** — Confirm the graph is acyclic. Check that every dependency alias in `dependencies` arrays has a matching entry in `packageAliases` with a valid 04t or 0Ho ID.
3. **Compute topological order** — Determine the build and install order. Packages with no dependencies build first; packages that depend on them build next.
4. **Apply layered decomposition** — If restructuring, group metadata into Base (shared objects/fields), Domain (business logic), and Experience (UI) layers. Move metadata between `packageDirectories` paths accordingly.
5. **Configure sfdx-project.json** — Update `packageDirectories`, `dependencies`, and `packageAliases` to reflect the desired DAG. Ensure exactly one directory has `"default": true`.
6. **Build and test in order** — Run `sf package version create` for each package in topological order. Fix dependency resolution errors before proceeding to the next package.
7. **Set up CI/CD sequencing** — Configure the pipeline to build and install packages in topological order, passing 04t IDs from upstream stages to downstream stages.

---

## Review Checklist

Run through these before marking work in this area complete:

- [ ] Dependency DAG is acyclic — no circular references between packages
- [ ] Every dependency alias in `dependencies` arrays resolves to a valid entry in `packageAliases`
- [ ] Exactly one `packageDirectories` entry has `"default": true`
- [ ] No metadata file appears in more than one package directory (no source duplication)
- [ ] Unpackageable metadata (profiles, org settings) is in a separate unpackaged directory, not in a package
- [ ] CI/CD pipeline builds and installs packages in topological order
- [ ] Each package's Apex tests pass independently (no cross-package test dependencies)

---

## Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

1. **Dependency version pinning with LATEST vs. explicit build** — Using `"versionNumber": "1.2.0.LATEST"` in a dependency resolves to the latest build of that major.minor.patch at version-create time. If an upstream team creates a new build, your next version create silently picks it up. Pin to an explicit build number in production pipelines to avoid surprise regressions.
2. **Package install order is not validated by the CLI** — `sf package install` does not check whether dependencies are already installed before attempting installation. It simply fails with a `MISSING_DEPENDENCY` error. Your pipeline must enforce topological order.
3. **Removing a component from a package requires deprecation** — Once a component (field, object, class) is in a released package version, removing it from source and creating a new version causes an error. You must deprecate the component first or use `--skip-ancestor-check` (which breaks upgrade paths).

---

## Output Artifacts

| Artifact | Description |
|---|---|
| Dependency DAG diagram | Visual or textual representation of which packages depend on which, including install order |
| sfdx-project.json | Updated project configuration with correct packageDirectories, dependencies, and aliases |
| CI/CD pipeline config | Stage definitions showing topological build and install order |
| Package decomposition plan | Document mapping metadata types to target packages with rationale |

---

## Related Skills

- unlocked-package-development — Single unlocked package creation, versioning, and installation; use alongside this skill when building individual packages within the multi-package graph
- second-generation-managed-packages — 2GP managed package ISV workflows; relevant when the multi-package architecture includes managed packages
- scratch-org-management — Scratch org configuration for multi-package development; scratch org definitions must include dependent package features
- github-actions-for-salesforce — CI/CD pipeline implementation; use when sequencing multi-package builds in GitHub Actions

Related Skills

unlocked-package-development

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when designing, creating, versioning, or installing unlocked packages: package directory configuration in sfdx-project.json, namespace management, package dependencies, version lifecycle (beta vs. released), ancestor versions, installation keys, and subscriber installation via sf CLI or Package Install UI. NOT for 2GP managed packages (ISV packaging with namespaces, push upgrades, or AppExchange listings), 1GP managed packages, change set deployments, or scratch org setup.

omnistudio-multi-language

8
from PranavNagrecha/AwesomeSalesforceSkills

Localize OmniScripts, FlexCards, and DataRaptors using Label-based translation, multi-language JSON, and locale-aware number/date formatting. NOT for Salesforce Translation Workbench alone.

lwr-site-development

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when building or customizing sites on the Lightning Web Runtime (LWR) in Experience Cloud — including component authoring, custom theming with --dxp hooks, layout components, and publish lifecycle management. Trigger keywords: build LWR site Experience Cloud, Lightning Web Runtime custom theme, LWR component development community, Build Your Own LWR template, Microsite LWR, lightningCommunity__Theme_Layout, --dxp styling hooks. NOT for Aura-based communities (Build Your Own Aura template). NOT for standard Experience Builder drag-and-drop configuration without code.

experience-cloud-multi-idp-sso

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when configuring multiple identity providers (OIDC and/or SAML) on a single Experience Cloud site or across tenant-specific portals in the same org — covering auth provider registration, Start SSO URL routing, Federation ID mapping, RegistrationHandler implementation, and simultaneous SP+IdP topology. Trigger keywords: multiple identity providers Experience Cloud, multi-tenant SSO community portal, vendor and citizen portal same site, OIDC SAML both on login page, tenant-specific login routing community. NOT for internal Salesforce employee SSO configuration. NOT for single auth provider setups — see experience-cloud-authentication for basic SSO.

data-cloud-activation-development

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when building developer-driven Data Cloud activation surfaces: webhook Data Action Targets with HMAC-SHA256 signing, Salesforce Platform Event data actions, Data Cloud-Triggered Flows on DMO insert, or Marketing Cloud journey triggers. Triggers on: webhook data action target, Data Cloud triggered Flow not firing, HMAC secret key for data action, platform event from Data Cloud, DMO insert trigger. NOT for configuring standard admin-level Activation Targets (SFTP, ad platform segment publishing, CRM segment activation) — those require admin configuration skills, not this developer extensibility skill.

second-generation-managed-packages

8
from PranavNagrecha/AwesomeSalesforceSkills

2GP managed package development: creating managed packages with Dev Hub and Salesforce CLI, semantic versioning, patch versions, namespace linking, ISV AppExchange listing, and subscriber upgrade management. NOT for unlocked packages, unmanaged packages, or 1GP-only workflows.

package-development-strategy

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when deciding between Salesforce package development approaches — unmanaged, unlocked, 1GP managed, or 2GP managed — including namespace selection, ISV distribution requirements, upgrade path design, and AppExchange packaging strategy. Trigger keywords: should I use managed or unlocked package, Salesforce package type selection, 2GP vs 1GP managed package, namespace decision Salesforce, ISV AppExchange packaging, unlocked package strategy. NOT for individual package creation steps, scratch org setup, or day-to-day package version build commands.

managed-package-development

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when building or maintaining Salesforce first-generation managed packages (1GP) for ISV distribution — covers namespace registration, packaging org structure, PostInstall/UninstallHandler Apex interface, push upgrades, Flow version management, and subscriber org considerations. NOT for second-generation managed packages (2GP), unlocked packages, or AppExchange listing setup.

multi-currency-and-advanced-currency-management

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when designing or reviewing Salesforce multi-currency behavior, especially irreversible activation, `CurrencyIsoCode`, `convertCurrency()`, dated exchange rates, and Advanced Currency Management tradeoffs. Triggers: 'multi currency', 'advanced currency management', 'CurrencyIsoCode', 'dated exchange rate', 'convertCurrency'. NOT for ordinary numeric field calculations with no currency conversion or reporting concern.

multi-store-architecture

8
from PranavNagrecha/AwesomeSalesforceSkills

Multi-store Commerce architecture: shared catalog, localization, multi-currency, multi-language, and regional storefront design for B2B, D2C, and SFCC deployments. Trigger keywords: multi-store, regional storefronts, shared catalog, multi-currency commerce, localization, multiple WebStores. NOT for single-store setup, store creation basics, or non-Commerce use cases.

multi-site-architecture

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when designing a strategy for multiple Experience Cloud sites within one Salesforce org, selecting a domain and URL pattern, planning shared LWC component libraries, designing cross-site navigation, managing the org's 100-site quota, or deciding between multi-site vs multi-org for portal needs. Trigger phrases: 'multiple Experience Cloud sites architecture', 'multi-portal strategy Salesforce', 'cross-site navigation Experience Cloud', 'domain strategy community portals', 'shared components across sites', 'how many Experience Cloud sites can I have', 'customer and partner portal same org', 'regional sub-portals Salesforce'. NOT for single Experience Cloud site setup (use admin/experience-cloud-site-setup). NOT for Experience Cloud page layout or component development in isolation. NOT for multi-org strategy (use architect/multi-org-strategy).

multi-org-strategy

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when deciding whether to use multiple Salesforce production orgs, designing a hub-and-spoke integration topology, reviewing an existing multi-org architecture for risk, or troubleshooting cross-org integration failures. Trigger phrases: 'should we have separate Salesforce orgs', 'how do we share data between two orgs', 'we acquired a company that uses Salesforce', 'our EU data must stay in Europe', 'cross-org integration keeps hitting API limits', 'Salesforce-to-Salesforce stopped working', 'how do we do SSO across multiple orgs'. NOT for sandbox strategy (use sandbox-strategy). NOT for individual integration callout implementation (use integration/ skills). NOT for Named Credential configuration in isolation (use integration/named-credentials-and-callouts).