Start free
Andrew Hanna

Andrew Hanna

How to Automate Salesforce Deployments With Scratch Orgs

How to Automate Salesforce Deployments With Scratch Orgs

Short answer: automating Salesforce deployments with scratch orgs means your CI job creates a disposable org from a definition file, installs your dependencies, deploys your source, runs the tests, and deletes the org again. The pieces are a Dev Hub, a scratch org definition file, sfdx-project.json, and four or five CLI commands. The part that decides whether it survives contact with a real team is not the script, it is the scratch org limits.

When should you use a scratch org instead of a sandbox?

A scratch org is a disposable, source-driven org created from a configuration file, so its shape lives in your repository rather than in someone's memory. Use one when the environment should be defined by code and thrown away: per-feature development, per-pull-request validation, package build and install testing.

Stay on a sandbox when you need production-like data volume or a long-lived integration endpoint. Scratch orgs cap out at roughly 200MB of records and 50MB of files, and they expire (Salesforce Ben).

What goes in the scratch org definition file?

The definition file is the blueprint. Only edition is required, with values such as Developer, Enterprise, Group, Professional and the Partner equivalents. The keys worth knowing (Salesforce DX Developer Guide):

  • features: an array of add-on features to switch on.
  • settings: org and feature preferences in Metadata API format. Some capabilities, Experience Cloud among them, need a feature and a matching setting before they work.
  • objectSettings: sharing models and default record types per object.
  • release: pin the org to a Salesforce release instead of following the Dev Hub.
  • sourceOrg and snapshot: build from an org shape or from a point-in-time copy instead of a bare edition.
  • hasSampleData, orgName, adminEmail, country, language: the small stuff that makes a failure reproducible.

Keep one definition file per pipeline purpose. A CI definition should be minimal and fast; a demo definition can carry sample data. Mixing the two is how a pull request check turns into a three-minute wait.

How does your source get into the org?

Scratch orgs use source tracking, so you deploy your project into the org and pull changes back out. In the current CLI that is sf project deploy start to push and sf project retrieve start to pull; the older force:source:push and force:source:deploy commands were consolidated into it (Salesforce DX Developer Guide).

Dependencies come from sfdx-project.json. The CI job reads the namespace and package dependencies there and installs them before your own source lands, which is why a build that works locally but fails in CI is usually a dependency ordering problem, not a metadata problem.

What does the CI job actually run?

  1. Authenticate to the Dev Hub using a JWT key stored as a CI secret. Never an interactive login.
  2. Create the org: sf org create scratch --definition-file config/project-scratch-def.json --alias ci, with a duration set to the shortest useful value.
  3. Install package dependencies declared in sfdx-project.json.
  4. Deploy your source with sf project deploy start.
  5. Seed the minimum data the tests need, from a versioned file in the repo.
  6. Run Apex tests and publish the results, failing the job on coverage or assertion failures.
  7. Delete the org in a step that always runs, including when earlier steps fail.

Step seven is the one teams forget, and it is the one that quietly breaks the pipeline a week later.

Why do scratch org pipelines fail once the team gets busy?

This is where most guides stop, and where real pipelines actually break. Four things to plan for:

  • Allocation limits. Developer, Enterprise, Performance and Unlimited Edition Dev Hubs each allow 6 scratch orgs per day and 3 active at once (Salesforce Ben). Ten pull requests a day and a per-PR org do not fit in that. Check yours with sf org list limits before you design the workflow, not after.
  • Expiry. The default lifespan is 7 days and the maximum is 30. Any environment a human is asked to review must be created with an explicit duration, or it will vanish mid-review.
  • Creation latency. A cold scratch org plus dependency installs is dead time on every single run. Pre-warmed pools and snapshots exist precisely to move that cost off the critical path.
  • Data. Scratch orgs start empty. Seed from a versioned file rather than a manual export, or your tests pass for reasons nobody can reproduce.

If you are hitting the allocation ceiling, the honest options are to reserve per-PR orgs for changes that touch packaged metadata, use a shared long-lived org for everything else, or run a pool. Serpent gives every plan scratch orgs, and adds pre-warmed scratch org pooling on Scale and Enterprise so the org is waiting before the pipeline asks for it.

FAQ

Do I need a Dev Hub to use scratch orgs?

Yes. Scratch orgs are created against an enabled Dev Hub, which is also where your daily and active allocations are counted.

Can an ISV build packages this way?

Yes, and it is the standard path. Build and install the package version in a fresh scratch org on every run, so install failures show up in CI instead of at a subscriber.

What is the difference between an org shape and a snapshot?

A shape copies the configuration of an existing org into a new empty one. A snapshot copies a point-in-time scratch org, including what was already deployed to it.

Should every pull request get its own scratch org?

Only if your allocation supports it. With 3 active orgs, a busy repository needs pooling or a shared validation org instead.

More step-by-step Salesforce DevOps guides are in our SF Guides library.

Related Articles

Curious about faster shipping before you dive in? Let's talk

Commitment free!