SfSkills Domains Docs GitHub

Home / devops / api-version-management

api-version-management

Use this skill when auditing, upgrading, or standardizing Salesforce API versions across metadata components, sfdx-project.json sourceApiVersion, Apex classes, LWC bundles, Aura bundles, and integration endpoints. NOT for REST/SOAP API design patterns, OAuth configuration, or Metadata API deployment mechanics — use integration/api-versioning-strategy.

Open the skill folder on GitHub


API Version Management

This skill activates when you need to audit, standardize, or upgrade the API versions declared across a Salesforce metadata codebase. Every Salesforce metadata component carries an API version that controls which platform behaviors, fields, and features are available at runtime. Version drift — where different components run on different API versions — causes subtle behavioral inconsistencies, test failures, and eventual breakage when Salesforce retires old versions.


Before Starting

Gather this context before working on anything in this domain:


Core Concepts

1. The Three Layers of API Versioning

Salesforce API versions operate at three distinct layers, each independently configurable:

  1. Transport API version — the version in REST/SOAP endpoint URLs used by external integrations (e.g., /services/data/v63.0/). This controls which API resources and fields are visible to the caller.
  2. sourceApiVersion in sfdx-project.json — the default version used by the Salesforce CLI during sf project deploy and sf project retrieve. It sets the baseline for metadata operations but does not override per-component versions at runtime.
  3. Per-component apiVersion — declared in each component's metadata file (.cls-meta.xml, .js-meta.xml, .trigger-meta.xml, .cmp). This is the version the platform actually uses when executing the component. An Apex class at version 50.0 sees different System method signatures than one at version 63.0.

Version drift occurs when these three layers diverge. The most dangerous drift is between sourceApiVersion and per-component versions, because developers assume they are deploying at one version while the platform executes at another.

2. Salesforce API Retirement Policy

Salesforce publishes an API End-of-Life policy with a minimum 3-year deprecation notice. When a version is retired:

Two distinct waves have completed, and conflating them is the most common error in this area:

VersionsDeprecatedRetired
7.0 – 20.0before Summer '22Summer '22
21.0 – 30.0Summer '22Summer '25

So the "3-year notice" is visible in the second row: deprecation in Summer '22, retirement three years later in Summer '25. As of Summer '26 the 21.0–30.0 wave has already landed — a team planning against "the next wave" using the Summer '22 date is reasoning with three-year-stale runway. Calls to a retired version fail hard: REST returns 410 GONE, SOAP returns 500 UNSUPPORTED_API_VERSION, Bulk returns 400 InvalidVersion. Proactive scanning is essential because Salesforce does not automatically upgrade component versions.

3. LWC Component Versioning (Spring '25+)

Starting in Spring '25, Lightning Web Components require an explicit apiVersion in their .js-meta.xml file. Previously, LWC inherited the org's current version implicitly. This change means:

4. ApiTotalUsage Event Logs

The ApiTotalUsage event type in Event Monitoring records every API call with the version used. Query these logs to find external integrations still calling deprecated versions:

SELECT ApiVersion, Client, Count
FROM ApiTotalUsage
WHERE ApiVersion < 31
ORDER BY Count DESC

This data is critical for building an upgrade plan that covers runtime usage, not just static metadata.


Common Patterns

Pattern 1: Full Codebase Version Audit

When to use: Before a major Salesforce release, after inheriting a project, or when deprecation notices arrive.

How it works:

  1. Read sourceApiVersion from sfdx-project.json.
  2. Scan all *-meta.xml files for <apiVersion> elements.
  3. Scan .cmp and .app Aura files for <aura:component> or <aura:application> version attributes.
  4. Compare each component's version against sourceApiVersion and flag drift.
  5. Flag any component below the minimum safe version (currently 31.0).

Why not the alternative: Manual spot-checking misses components because a typical org has hundreds of versioned files scattered across classes, triggers, pages, components, and flows.

Pattern 2: Incremental Version Pinning

When to use: When upgrading all components at once is too risky (large codebase, limited test coverage).

How it works:

  1. Group components by current version into tiers.
  2. Upgrade the oldest tier first (highest risk of retirement).
  3. Run the full test suite after each tier upgrade.
  4. Update sourceApiVersion in sfdx-project.json only after all components reach the target version.

Why not the alternative: A big-bang upgrade changes runtime behavior across every component simultaneously, making it difficult to isolate regressions.

Pattern 3: CI Pipeline Version Gate

When to use: To prevent version drift from recurring after cleanup.

How it works:

  1. Add a pre-commit or CI check that scans *-meta.xml for <apiVersion>.
  2. Reject any component whose version is more than 2 major versions behind the project's sourceApiVersion.
  3. Reject any component below the absolute minimum (currently 31.0).
  4. Report drift percentage in CI output.

Why not the alternative: Without a gate, developers create new components at the CLI's default version while old components stay on legacy versions, re-introducing drift within a single sprint.


Decision Guidance

SituationRecommended ApproachReason
All components within 2 versions of targetBig-bang upgrade to current versionLow risk; behavior changes are minimal across adjacent versions
Components span 10+ version rangeIncremental tier-based upgradeIsolates regressions; allows targeted test runs per tier
External integrations on old versionsUpgrade transport API version separately, coordinated with external teamsTransport version affects API consumers outside your control
New project setupPin sourceApiVersion to current release, add CI gate immediatelyPrevents drift from day one
LWC bundles missing explicit apiVersionAdd <apiVersion> to every .js-meta.xmlRequired from Spring '25; implicit versioning is deprecated
Managed package developmentPin to the lowest version your subscribers needManaged packages must support the subscriber's minimum API version

Step-by-step instructions for auditing and upgrading API versions across a Salesforce project:

  1. Read sfdx-project.json — extract the sourceApiVersion value. This is the project's intended baseline. If it is missing, the CLI defaults to the latest version, which may not match component versions.
  2. Inventory all versioned components — scan the metadata source directory for every *-meta.xml, .cmp, .app, and .js-meta.xml file. Extract the <apiVersion> element from each. Record the component name, type, and version.
  3. Identify drift and retirement risk — compare each component's version against sourceApiVersion. Flag components more than 2 versions behind as drifted. Flag anything below version 31.0 as retirement-critical.
  4. Check runtime API usage — if Event Monitoring is available, query ApiTotalUsage logs to find external integrations using deprecated versions. Merge this data with the metadata inventory.
  5. Build the upgrade plan — prioritize retirement-critical components first, then drifted components, then cosmetic alignment. Group into tiers for incremental rollout. Document expected behavior changes per version jump using Salesforce release notes.
  6. Execute and validate — upgrade each tier by updating <apiVersion> in metadata files. Run the full test suite after each tier. Confirm deployment succeeds in a sandbox before production.
  7. Add a CI gate — implement a version-check step in the CI pipeline to prevent future drift. Set the minimum acceptable version to no more than 2 behind sourceApiVersion.

Review Checklist

Run through these before marking work in this area complete:


Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

  1. sourceApiVersion does not override per-component versions at runtime — many developers assume setting sourceApiVersion to 63.0 means all their Apex runs at 63.0. It does not. Each class executes at the version in its own -meta.xml. The sourceApiVersion only affects CLI retrieve/deploy operations.
  2. Apex behavior changes silently between versions — certain System methods change behavior across versions (e.g., String.valueOf() on null, SOQL relationship name resolution, trigger context variable availability). An Apex class at version 40.0 can produce different results than the same code at version 63.0, with no compile-time warning.
  3. Retired API versions cause hard failures, not graceful fallbacks — when Salesforce retires a version, REST/SOAP calls to that version return UNSUPPORTED_API_VERSION errors immediately. There is no automatic forwarding to the next supported version. Metadata components on retired versions may fail to deploy.

Output Artifacts

ArtifactDescription
API Version InventorySpreadsheet or table listing every component, its type, file path, and current API version
Version Drift ReportSummary of components that diverge from sourceApiVersion, grouped by severity
Upgrade PlanPrioritized, tiered plan for updating components with test checkpoints
CI Gate ConfigurationPipeline step or pre-commit hook that enforces version consistency

Package files