Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
Salesforce Developer
hard

How do you handle Apex class versioning over the lifetime of an org or package?

Apex classes carry an API Version (declared in metadata, e.g., 60.0 for Spring '24). Salesforce releases new API versions every release; older versions remain supported indefinitely (in practice, 3+ years).

Why version matters:

  • Each class compiles against its declared API version's behaviour.
  • Salesforce updates platform behaviour in newer versions while preserving old behaviour for old versions.
  • Classes calling each other can have different versions; behavioural quirks of the older version's class persist.

Common version-related issues:

  • A class on API v40 that uses an older method signature; calling code on v60 sees the legacy behaviour.
  • A new feature only available at API v55+ — old class can't use it without bumping its version.
  • A breaking change in a newer API version — old classes are insulated, new classes adopt the new behaviour.

Strategy in customer orgs:

  1. Bump API versions deliberately — when you upgrade a class, decide whether to bump its API version. Bumping may unlock new features but may also introduce subtle behaviour changes.
  2. Read release notes for each API version — Salesforce documents API-version-related changes.
  3. Test thoroughly when upgrading versions — particularly anything date/time, sharing, or aggregation-related.
  4. Don't upgrade for the sake of upgrading — old API versions are stable; only upgrade when you need a feature or fix.

Strategy in managed packages:

This is harder. Managed packages have:

  • Package version — your own internal version (1.0, 1.1, 1.2, 2.0).
  • API version per class — what each class compiled against.
  • Subscriber API version — what's installed in customer orgs.

When you publish a new package version:

  • Classes can be added, modified, deprecated.
  • `global` method signatures cannot change — backward-compat forever.
  • `public` methods are flexible internally; not visible outside the package.
  • API version of a packaged class affects how it behaves in subscriber orgs.

Deprecation patterns:

  • `@deprecated` annotation on a class or method — marks it but doesn't break it.
  • Document migration path in release notes for each version.
  • Long deprecation windows — typically 2-3 major versions before removal.

Forward compatibility tools:

  • Stable interfaces — define global interface that doesn't change; concrete classes evolve behind it.
  • Versioned URLs for REST endpoints (/v1/, /v2/).
  • Feature flags via Custom Metadata to toggle new behaviour while keeping old code path.

Tooling:

  • Salesforce DX tracks API versions in sfdx-project.json (default version) and per-class metadata.
  • Lightning Inspector / Setup -> Apex Classes show installed class versions.

A mature versioning strategy: the codebase's classes are mostly current API version, with a clear list of "legacy classes pinned to older API version because of specific behaviour we depend on" maintained as technical debt.

Why this answer works

Senior. The "global is permanent" + deprecation patterns + package vs org distinction are senior signals.

Follow-ups to expect

Related dictionary terms