Skip to content

How to replace a value per environment

Sometimes a piece of metadata must hold a different value in each stage org — an endpoint URL, a named-credential principal, a running user, a certificate name. Value replacements handle this: a Salesforce CLI source-behavior feature driven by a replacements block in sfdx-project.json, which the toolchain feeds only by setting SF_DEPLOY_TARGET to the stage it deploys to (see the branch, environment and org model).

Add a replacement

Add a replacements array to sfdx-project.json. Each entry names what to find, what to put there, and — optionally — the condition under which it applies:

{
    "packageDirectories": [{ "path": "force-app", "default": true }],
    "sourceApiVersion": "66.0",
    "replacements": [
        {
            "filename": "force-app/main/default/namedCredentials/My_API.namedCredential-meta.xml",
            "stringToReplace": "https://placeholder.example.com",
            "replaceWithFile": "config/replacements/my-api-endpoint.uat.txt",
            "replaceWhenEnv": [{ "env": "SF_DEPLOY_TARGET", "value": "UAT" }]
        }
    ]
}

On any deploy or push where SF_DEPLOY_TARGET is UAT, sf replaces the placeholder string in that file with the contents of the replacement file. Add one entry per (file, stage) pair you need.

Key it on the deploy target

The pipeline sets SF_DEPLOY_TARGET to the upper-cased stage name for the org it is deploying to, and falls back to SIT for scratch-org and local runs (see the environment variable reference and the branch/org model). So:

  • Use SIT, UAT, PRODUCTION (upper-case) as the replaceWhenEnv values — they must match the stage names the pipeline produces.
  • A replacement with no replaceWhenEnv applies on every deploy.
  • Because the default is SIT, a value: "SIT" entry also covers scratch orgs and local pushes.

Other forms

regex, replaceWithEnv, glob and the rest of the schema are in the Salesforce DX Developer Guide: Replace Strings in Code and Metadata.

Verify

Set SF_DEPLOY_TARGET to the stage you want to check in your shell, then run a validate-only deploy against a scratch org or a stage and confirm the value that landed:

npm run deploy:validate -- --target-org my-uat-sandbox

deploy:validate runs the orchestrator's workarounds — custom pre/post deployment hooks are skipped in validate mode — as a check-only, dry-run deploy. Inspect the generated output, or deploy for real and check the component in the org. If the value did not change, check that replaceWhenEnv matches the SF_DEPLOY_TARGET in play and that the file path or glob actually matches the component.

Do not call sf project deploy directly

Calling the Salesforce CLI's own deploy command bypasses the orchestrator — no workarounds, no delta logic. Verify replacements through npm run deploy:validate.

Replacement files are committed in clear text

replaceWithFile reads a tracked file in the repo. Do not put secrets there — use replaceWithEnv pointing at a secured repository variable for anything sensitive.