Always Build in a Sandbox. (Except When You Don't. Or can't.)
It’s a mantra oft-repeated: “Never build directly in production.” If you’re an admin you should be building new automation, new objects and fields, or otherwise messing with your metadata only in a sandbox environment. And I agree. I regularly admonish my clients and my mentees to build only in a sandbox and to test thoroughly before deploying to production. It takes extra time but it’s an important safeguard.
I’ve already argued that keeping some test data in production makes sense. I might as well lose the rest of my credibility right now:
There are times to build directly in production.
Honestly, we all do it. Except in the strictest and most regulated organizations/industries, it’s not even that uncommon. Sometimes “building” in production is reasonable, or perhaps even necessary.
What Constitutes “Building” Anyway?
I don’t think anyone would argue that it’s wrong to make a new report directly in production. [Would you???] It’s already a constant battle to get users to learn to edit and build their own reports. If you’re going to insist they be built in a sandbox you’re mandating that reports are only built by your Salesforce admin team. I believe in teaching my users to fish.
Of course anything one might say about building reports is going to apply to dashboards as well...
I can see an argument that reports and dashboards fall into a strange gray area where they, themselves, are metadata but they’re so dependent on data that maybe they’re a different category. Plus reports and dashboards are about showing the data that’s in the org, they’re not automation, or changes to the user interface, or the like.
But the Lightning Report Builder has the ability to make row-level formulas. (In the past that would have required an admin to build a formula field for a specific reporting need, so bring ‘em on!)
If it’s OK to process a formula in the context of running a report, that seems a very short distance from actually creating a formula field, no?
That's why I would say that creating a formula field directly in production seems fairly reasonable.
[Brief aside: If you’re doing this, take steps to test and validate before you let users see the new field: Uncheck the box that adds the field to page layouts. Maybe restrict field level security until it’s ready. You can look at the field in the meantime using a report. And note that modifying an existing field probably is a category of its own because that has potential spillover effects. Then again, if you find that a formula field is broken, I’d say working on a fix directly in production is fairly reasonable.]
Here are a bunch of purely metadata modifications that I’m going to argue are safe to do directly in production:
Edit page layouts and compact layouts
Modify Lightning Record Pages
Make a new Quick Action
Those are all changes to the user interface but don’t impact data itself.
Sure, depending on how extensive the page modifications are, you could confuse users a bit. Try to make things obvious or else give a heads-up.
It’s OK to “move people’s cheese” as long as it’s still somewhere in the same fridge they last saw it.
In the same vein, modifying a display-only screen flow should be safe. Or, for that matter, editing the display portions (only!) of a flow that also runs data operations. Go ahead and fix that typo you noticed.
Similar to my argument for formula fields, I think you could make a new rollup summary (traditional rollup summaries, DLRS rollups, or NPSP Customizable Rollups). You’re going to learn more testing the rollup against the messy real data that’s in production than what you have to work with in a sandbox. As above: keep the field hidden from users until you've perfected it.
And here's a good tip from Stephanie Foerst for a good time to build directly in prod: “When there's a production issue and you can easily resolve it.”
Modifying Metadata in Production
So we’ve determined that the difference between “data stuff” and metadata is not going to provide a bright line guideline.
If it’s a matter of degree not type, I think we’re going to have to start considering the impact of your actions.
I know: Bummer. Considering the consequences of our actions is sooooooo haaaardddddd.
If you’re going to modify metadata directly in production—and I think we all know you are—the best advice I can give is to think about when it’s OK and when it’s not.
1. Is it gonna break stuff?
Things that can break stuff include:
They don’t just stop users from getting things wrong–they stop integrations and Apex code, too.
But here you really have to consider what the automation is doing.
2. Is it going to escape the environment?
Anything that sends an email.
Integrations (though sometimes you don’t have a sandbox option on the other end of the integration)
3. Do I need to do a lot of testing that will result in records users might stumble upon?
4. Am I building new and/or self-contained functionality?
I would normally say that a new object is so self-contained that it makes perfect sense to build in a sandbox. But I asked around and others were pretty OK with building new objects in prod exactly because they are self-contained...
Most of the time, work in sandbox.
But just one field…? Go for it.
5. Experience Cloud
I feel like this is almost a topic of its own (that should be written by someone that knows Experience Cloud/Communities better than I do). It’s a pain to deploy a built out Site from sandbox. Making changes in prod (but waiting to publish them) is pretty common.
6. [Special Case] Record Types
This is a very specific use case that Peter Churchill pointed out to me: If you create a record type in production “they maintain their Ids in each environment, but Sandbox to Prod will create a new Id.” Sometimes it’s easier to build automation based on record type Ids, so this will save you some hassle. Personally, I prefer to have my automation look up record types by API name rather than rely on the Id being constant.
Don’t Punk Yourself!
Here’s the thing about making any modifications in production: They’re not likely to flow down into sandboxes—you’re going to forget to do that. In any environment where there is simultaneous development happening in sandboxes—even if you are the one doing the building in both environments—if you make a modification in production there’s a chance of undoing your work later when you deploy from the sandbox.
Say I have an active sandbox named “mbkdev” where I’m building a child object to contact. In that sandbox I modify the contact page layout to add the related list for this new object. I make no other changes to the contact layout. My work in this sandbox is taking some time, so I haven’t deployed my new object and contact page layout yet.
Meanwhile, I get a request for a formula field on contact to translate from Birthdate to display the contact’s age. (I know, you probably forgot there isn’t a standard field for this!) This is an eminently reasonable request and one that I want to deliver quickly. So I throw together the formula field and I drop it onto the page layout. While I’m at it, I decide to move demographic fields together into their own tidy section.
Three weeks later we finish testing the work in the mbkdev sandbox and we’re ready to deploy our new object. Since we modified the contact page to include the new object’s related list, we put that layout in our change set. But the Age field doesn’t even exist in mbkdev and the demographic fields are in their (haphazard) positions from the moment the sandbox was first created. As soon as our deployment goes live, the contact layout has reverted to its state from three weeks back, with only the addition of our new related list.
Oops. I’ve just undone my own work. How foolish do I feel?
[This is a purely hypothetical situation. I have never allowed this to happen IRL.]
It’s a challenge to keep sandboxes in sync. If you have deployment procedures, use them.