Does Trunk-Based Development Even Work in Salesforce?

Trunk-based development sounds elegant and modern, but when you bring it to Salesforce's metadata-driven platform, fundamental limitations start to surface. Here's why.

6 min readDevOps Strategy

# TRUNK-BASED DEVELOPMENT

Traditional Systems
Build-Based
Code
Artifact
Deploy
✅ Works great
VS
Salesforce
Metadata-Driven
Metadata
No Build
Push
❌ Breaks model

Trunk-based development sounds elegant. Fast, simple, modern. But when you bring it to Salesforce, things start to crack. Here's why.


Let's Back Up: What Even Is Trunk-Based Development?

If you're from the Salesforce ecosystem, chances are you've heard this term thrown around by backend engineers or DevOps architects — sometimes with an almost mythical air of superiority.

But let's be honest: most Salesforce developers haven't lived in GitHub-heavy workflows for long. And even fewer have seen trunk-based development done right.

So here's the basic idea:

Trunk-based development is a branching model where all developers work off a single long-lived branch — usually main. Instead of maintaining separate persistent branches (like develop, UAT, or release), every change is either committed directly to main or merged in quickly via short-lived feature branches.

The ideal flow looks like this:

  • A developer spins up a feature branch in the morning
  • Works on their changes, runs tests, validates it
  • By end of day, merges it into main via PR
  • CI pipelines ensure build health and test coverage
  • Done. No lingering branches. No sync chaos.

Some teams go even further — keeping main as the sole focus and committing frequently, trusting their pipelines, rollback mechanisms, and process hygiene. Others rely on feature flags to selectively activate features, regardless of whether they use feature branches or not.


Why It Works (Elsewhere)

In traditional engineering stacks, this is not only feasible — it's ideal.

Why?

Because backend systems are build-based. You check out the codebase, compile it into an artifact, and deploy that same build to as many environments as needed — dev, staging, prod, etc.

All it really takes is one build. Drop it into another virtual machine, and you've got a new environment. That's the magic.

You get:

  • Environment flexibility
  • Easy rollbacks
  • Immutable artifacts
  • Infrastructure as code

It's fast, scalable, and replicable.


Now Enter Salesforce… and Things Start to Break

Salesforce is not a build-based platform. It's metadata-driven.

Everything — from Apex classes to page layouts to validation rules — is metadata. Even Apex, which looks like code, is compiled and interpreted only within the platform. There's no JAR file. No WAR. No binary artifact.

There is no true "build" — just a bundle of metadata waiting to be pushed to another org.

That means you can't:

  • Create a standalone artifact for deployment
  • Spin up local Salesforce environments
  • Duplicate an org state with a single file

Each sandbox is a real org — physical, stateful, and deeply tied to the platform.


No Build, No Repeatability

In a traditional CI/CD flow, you take the same build and run it in:

  • Your local machine
  • A dev integration server
  • A QA box
  • Pre-production
  • And eventually, production

Each is just another container or VM running the same artifact.

In Salesforce, there's no such luxury. You can't "replay" a build. Instead, you:

  • Push metadata
  • Resolve dependencies manually
  • Re-run tests inside a live org
  • Hope it behaves the same as the last org

This is where trunk-based development starts to fall apart.


Version Control Is Not Enough

Yes, you can still use Git. Yes, you can store everything in the main branch. Yes, you can automate validation flows.

But that doesn't make it trunk-based development in the full sense of the term.

Why?

Because without:

  • A true build artifact
  • Environment spin-up automation
  • Reliable metadata sync across sandboxes

…you're left managing manual deployments between rigid, long-lived environments.

And no, sandboxes aren't ephemeral. You don't get fresh environments per commit. You get a sandbox refresh every 29 days — if you're lucky.


Even Feature Flags Don't Save You

Feature flags are great. They allow teams to:

  • Hide incomplete functionality
  • Gradually roll out changes
  • Decouple deployment from release

But they don't solve the core issue here.

You can use feature flags in any branching model — even with long-lived branches.

So while feature flags are helpful, they're not unique to or required by trunk-based development — and they certainly don't enable it in the Salesforce world.


In Theory: Trunk-Based.

In Practice: You Hit a Wall.

You may still version control your Salesforce metadata in a main branch. But that's not trunk-based development — it's just Git hygiene.

Without:

  • Fully automated deployments
  • Consistent environments
  • Isolated test validation

…you're managing metadata across sandboxes by hand, hoping nothing breaks.


Scratch Orgs: A Promising But Underused Path

To be fair — Salesforce does offer something that resembles the ephemeral environment idea: scratch orgs.

These were introduced specifically to enable modern DevOps workflows. In theory:

  • You define a config file that specifies the edition, features, and shape of the org
  • Specify the edition, features, and installed packages
  • Spin up an isolated environment programmatically via CLI
  • Push metadata directly from main
  • Validate or develop without interfering with other environments

Sounds great, right?

But here's the reality — most teams don't treat scratch orgs as their daily driver.

Why?

Because in practice, they come with friction:

⚙️ Environment inconsistency – Scratch orgs don't always spin up the way you expect. The more complex your org (managed packages, integrations, custom settings), the more likely something will be missing or misconfigured.

📦 Installed package setup – Scratch orgs don't come pre-loaded with the third-party packages your org depends on. You have to script the installation and manually do each package configuration and sometimes wait for long install times.

🧪 Test data complexity – If your object model is non-trivial, you'll need a robust data seeding process. That includes parent-child relationships, record types, picklist dependencies — none of which come "for free."

🔁 Setup burden increases with org size – As org complexity grows, so does the effort to make a scratch org match reality. At some point, teams prefer to just work with a long-lived sandbox that's already set up correctly.

So while scratch orgs are technically powerful, their real-world usability is limited unless you've invested heavily in automation and tooling. Most teams still lean on persistent environments like dev, QA, or pre-prod sandboxes — because they "just work."


So Where Does That Leave Us?

Some form of long-lived branching is often necessary for Salesforce.

Whether it's a preprod branch, an integration branch, or a sandbox-specific flow — we need to respect the fact that Salesforce has real limitations that don't bend to modern DevOps fantasies.

Main-only development? Not without heavy investment. Real trunk-based flow? Not unless Salesforce radically changes how metadata, environments, and deployment work — or scratch org usage becomes the norm.

We'll explore long-lived branches — and why they may not just be a fallback, but a requirement — in the next part.

Tags:SalesforceDevOpsTrunk-Based DevelopmentCI/CDGitMetadata