Target: Spring '26. Sources: Scratch org definition, Sandbox types, Sandbox Preview.
1. Scratch org definition
{
"orgName": "Order Management dev",
"edition": "Enterprise",
"features": ["EnableSetPasswordInApi", "Communities", "PersonAccounts"],
"settings": {
"lightningExperienceSettings": { "enableS1DesktopEnabled": true },
"securitySettings": { "passwordPolicies": { "enableSetPasswordInApi": true } },
"automationSettings": { "enableFlowDeployAsActiveEnabled": true }
}
}
Keep it minimal and honest: every feature and setting here is a claim that production has it too. When a scratch org needs a setting production does not have, the pipeline is hiding a difference rather than testing one.
A repeatable dev environment is three steps, and they belong in a script:
sf org create scratch --definition-file config/project-scratch-def.json --alias dev --duration-days 7 --set-default
sf project deploy start --target-org dev
sf apex run --file scripts/apex/seed.apex --target-org dev # or sf data import tree --plan data/plan.json
Packages the project depends on install in the same script, by version, so nobody hand-installs anything.
2. Sandbox strategy
| Type | Copies | Refresh | Good for | Watch |
|---|---|---|---|---|
| Developer | Metadata only | 1 day | Individual dev work when scratch orgs are impractical | Small data storage; seed it |
| Developer Pro | Metadata only | 1 day | Same, with more storage for test data | Same |
| Partial Copy | Metadata + a sampled data set | 5 days | Integration testing and UAT | Sampling rules decide what you can actually test |
| Full | Metadata + all data | 29 days | Performance testing, migration rehearsal, release rehearsal | Refresh takes a long time; mask or scramble personal data |
Rules that prevent the usual mess:
- Name sandboxes after their purpose (
uat,intg,perf), never after people. - Sandbox refresh wipes everything, including the org-specific configuration somebody set by hand. Keep a post-refresh script: deploy the branch, apply the environment's Custom Metadata, create integration users, reactivate the Named Credentials and their principals, disable outbound email.
- Personal data in a Full sandbox is production data. Mask it, restrict access, and delete the sandbox when the project ends.
- Sandboxes drift because admins work in them. Retrieve or re-deploy from git regularly, and treat any surprise diff as a review item, not an inconvenience.
3. Sandbox Preview — three times a year
Salesforce upgrades sandboxes on a preview instance before production. During each preview window:
- Confirm which of your sandboxes are on a preview instance (or create a preview sandbox in the window).
- Deploy the current release branch to it.
- Run the whole suite: Apex tests, Flow Tests, Jest, the browser journeys, and any integration contract tests.
- Read the release notes' "critical updates" and "retirements" alongside the failures — most preview breakage is an announced change nobody routed to the team.
- Log what broke and fix it before the production upgrade, not after.
This is the single highest-value recurring activity in Salesforce delivery and the one most often skipped.
4. Release checklist
Before the window
- Release branch cut and frozen; every change has a reviewed pull request
- Full validation green against production (
deploy validate,RunLocalTests), job id recorded with the commit SHA - Destructive changes manifest reviewed by a second person
- Flow activation policy confirmed; flow coverage checked if deploying active flows
- Data migration or backfill scripts rehearsed in a full sandbox, with row counts
- Permission sets and Custom Metadata for the new features prepared for the target org
- Integration owners told about contract changes; External Client App credentials in place
- Rollback strategy chosen and, for a risky release, rehearsed
- Business sign-off recorded against the release notes
In the window
-
sf project deploy quick --job-id … - Post-deploy steps in order: Custom Metadata, permission set assignment, feature switch on, scheduled jobs re-scheduled
- Smoke test: one journey per changed area, by a human, in production
- Monitoring watched for an hour: Apex exception emails, integration error object, event subscription status, API usage
After
- Release record updated with the SHA, job id, and what was skipped
- Feature switch state written down
- Anything learned added to this checklist
5. Environment differences without a sed
| Difference | Mechanism |
|---|---|
| Endpoint URLs and credentials | Named Credential + External Credential per org; same developer name everywhere |
| Feature toggles | Custom Metadata records, deployed per environment, or a custom permission |
| Volumes and thresholds | Custom Metadata, never constants in Apex |
| Email suppression | Deliverability set to System email only in every non-production org, checked after each refresh |
| Scheduled jobs | A post-deploy anonymous Apex script that (re-)schedules them idempotently |
| Integration users | Created by the post-refresh script, with their permission sets, never by hand |