Among other things, our custom settings include URLs for production servers and credentials to access those servers.

Arguably, some of these things should probably be Named Credentials, but the authentication for the relevant servers don't seem to match the paradigm offered by Named Credentials (see, for example, Is our “Identity Server” a Good Use Case for Named Credentials and if so, how should I use Named Credentials Instead?).

Be that as it may, between data security on Salesforce and data integrity off Salesforce, while we may want to give someone a current copy of production to work in, we may not want to include any/all the custom settings which live in production.

Is there a good, easy way to keep these out of our clones?

  • 2
    First idea which comes to my mind is to use SandboxPostCopy interface and delete desired custome settings there Oct 2, 2020 at 10:05

1 Answer 1


SandboxPostCopy Interface will meet the need. Select it to run when you refresh and it allows you to run a script before activation of the sandbox. There's some limitations (ex. Can't make callouts to update those that need that) but you can do what you need here with updating custom settings.

If you have test servers, you could store that URL to update appropriately so users can test or you can update it to remove it.

I've also used this script for other use cases:

  • Deleting scheduled jobs
  • Activating Test Users
  • Changing User emails

Below is a quick example

public without sharing class SandboxRefreshScript implements SandboxPostCopy {
    public void runApexClass(SandboxContext context) {
        //updating custom setting to remove URL
        String sandboxName = context.sandboxName(); //can get sandbox name if helpful

    private static void updateCustomSettings() {
    List<Server_URL__c> serverURLs = new List<Server_URL__c>([SELECT Id,URL__c FROM Server_URL__c]);
        for(Server_URL__c serverURL : serverURLs){
            serverURL.URL__c = '';
        update serverURLs ;

Some notes/considerations:

  • You will have to remember to type in the Apex Class name when creating "new" sandboxes. enter image description here
  • If you're refreshing an existing sandbox where you already refreshed once with the script, it remembers your sandbox options (auto activate and Apex Class). This seems to be (based on quick testing) saved per environment and across users. enter image description here
  • If you have relevant URLs for specific sandboxes, a custom metadata type is useful to map based on sandbox name (or other identifier) to the right URL so you could have just one custom setting that controls what all of your code may point to (using context.sandboxName in the script gives you the name). Below is an image for reference where each integration would get a row and the URLs for each environment. enter image description here
  • Is there a way to set this (or such a script) as default when going through the create Sandbox dialog, so nobody needs to remember to do this? Would you hardcode test values into the script or create extra variables to hold them (or something else)? Oct 2, 2020 at 12:05
  • 1
    If you're refreshing a sandbox again (and selected the script the first time), it seems to default to your last "sandbox options" so it does auto-populate after using it the first time. However, there isn't a way to make it default for "new" sandboxes across the board. I use a custom metadata type (as we have servers across many test tracks with specific URLs) and have a mapping of sandbox name to what URL needs to be put in a custom setting. Oct 2, 2020 at 12:19
  • Is the default perpetuated across users, so if somebody else creates a sandbox, they get the same default? Or does every admin need to learn to do this, so it becomes a training issue? Trying to imagine how you are using custom metadata.... if I understand correctly, effectively every environment will know about every environment or at least about all the test environments? Oct 2, 2020 at 14:55
  • 1
    I edited the answer to include an image which I think is easier to visualize how you might do it. We utilize context.sandboxName() in the refreshscript to essentially populate one custom setting field. Then, we have a utility class that fetches integration URLs based on this value with a custom metadata type with relevant field names. Allows us to point all our various callouts in one easy edit. For your second question, yes - it seems it saves per environment the last refresh state (irrespective of user). Oct 2, 2020 at 15:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .