# Environments, Sandbox Preview and the release checklist

Target: Spring '26. Sources: [Scratch org definition](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_scratch_orgs_def_file.htm), [Sandbox types](https://help.salesforce.com/s/articleView?id=platform.data_sandbox_environments.htm&type=5), [Sandbox Preview](https://help.salesforce.com/s/articleView?id=platform.sandbox_preview.htm&type=5).

## 1. Scratch org definition

```json
{
  "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:

```bash
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:

1. Confirm which of your sandboxes are on a preview instance (or create a preview sandbox in the window).
2. Deploy the current release branch to it.
3. Run the whole suite: Apex tests, Flow Tests, Jest, the browser journeys, and any integration contract tests.
4. Read the release notes' "critical updates" and "retirements" alongside the failures — most preview breakage is an announced change nobody routed to the team.
5. 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 |
