Named Credentials in Sandboxes: The DevOps Lifecycle Guide
One of the most persistent pain points for Salesforce architects and developers is the post-refresh sandbox experience. You refresh your Full or Developer Pro environment, log in with high expectations, and immediately hit an authentication failure on your outbound integrations. You soon realize your Named Credentials didn't migrate.
In this guide, we’ll demystify why Salesforce handles Named Credentials this way and provide a professional, scalable approach to managing them throughout your CI/CD lifecycle.
Why Named Credentials Don't Copy
When you trigger a sandbox refresh, Salesforce performs a deep copy of your production metadata. However, for security and compliance reasons, Named Credentials are intentionally excluded.
Think of it this way: a Named Credential is a bridge between your org and a potentially sensitive third-party service. Copying the stored credentials (like OAuth tokens, API keys, or password-based secrets) from Production to a Sandbox would be a security nightmare. It would allow developers in a lower-trust environment to potentially invoke production API endpoints with production-grade authorization. By forcing a manual setup or scripted redeployment, Salesforce ensures that you intentionally configure your sandbox integrations to point to development or staging endpoints.
The Immutable Infrastructure Approach
Many teams treat Named Credentials as "manual configuration" handled by admins post-refresh. This is a technical debt trap. If your environment setup takes four hours of manual clicking after every refresh, your pipeline is not truly continuous.
Instead, we recommend an Infrastructure-as-Code (IaC) approach. While you should never store plaintext secrets in your Git repository, you can store the metadata definition of the Named Credential.
Step 1: Extract Metadata via SFDX
First, pull your existing Named Credential definitions from your source of truth (or a correctly configured scratch org) using Salesforce CLI:
sfdx project retrieve start -m NamedCredential:MyApiIntegration
This will generate a .namedCredential-meta.xml file. Note that this file contains the definition (endpoint, auth protocol, etc.) but excludes the actual sensitive secrets.
Automating the Post-Refresh Workflow
Since we cannot deploy the sensitive secret components, we must automate the "plumbing" part of the setup.
Using External Credential Providers
If you are using the modern "External Credentials" architecture introduced in recent releases, you have a cleaner path. You can bundle the External Credential and Named Credential structure as part of your deployment package, leaving only the final "Authentication Parameter" (the API key or OAuth secret) for the developer or a secure vault to inject.
The Deployment Scripting Pattern
If you have a high volume of integrations, consider using a custom post-refresh script in your CI/CD runner (e.g., GitHub Actions, Jenkins, or GitLab CI). Using the sfdx force:source:deploy command, you can push the structural metadata, and then use a simple Apex script to update the remaining parameters.
Example post-refresh.apex template:
// This script assumes the Named Credential structural metadata is already present
// Update the Auth parameters via Tooling API or custom settings approach
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:MyNamedCredential');
// In a sandbox, we inject the staging key into a custom metadata record
// or a secure Protected Custom Setting to be used by an auth provider
System.debug('Named Credential ready for staging secret injection.');
Managing Secrets Safely: Never Commit to Git
The biggest risk in solving this problem is the temptation to store raw credentials in Custom Metadata Types (CMDT) or static resources. Do not do this.
If you have a CMDT that stores a password, it will be retrieved by your CI/CD tool, pushed to your Git repo, and suddenly your production secrets are readable by anyone with access to your repository.
The Recommended Strategy:
- Version Control: Commit the structure (the
NamedCredentialandExternalCredentialXML files). - Vault Injection: Use a secret manager (like AWS Secrets Manager, HashiCorp Vault, or GitHub Secrets).
- Post-Refresh Automation: Create a small automation utility that fetches the secret from your vault and uses a
NamedCredentialservice-level Apex call to populate the missing bits during the sandbox "warm-up" phase.
Key Takeaways
- Security by Design: Salesforce excludes Named Credentials from refreshes to prevent accidental cross-environment data leakage. Embrace this as a security feature, not a bug.
- Separate Structure from Secrets: Use SFDX to deploy the metadata structure of your integrations, but treat the authentication secrets (tokens, keys) as environment-specific variables.
- Avoid the CMDT Trap: Storing credentials in Custom Metadata Types is insecure and compromises your source control integrity. Always use a proper secrets management solution.
- Automate the Glue: Build a post-refresh CLI script that deploys the skeleton of your integration, then maps the correct environment secrets based on the current Org ID or target environment name.
By shifting your mindset from "manually configuring" to "automating the deployment of integration skeletons," you turn a tedious manual process into a robust, repeatable DevOps workflow.
Leave a Comment