Content last updated December 2020. Roadmap corresponds to Spring ‘21 projections.
Our forward-looking statementapplies to roadmap projections.
You want to customize Salesforce. It may be something simple, like adding a field; or maybe it is much more complex, like a custom application with dozens of objects and thousands of lines of code.
How do you deploy into production? The answer, of course, is “it depends". The method you choose for moving a change into production will depend on many factors, including the urgency of the change, its complexity, the size of your team, and the metadata involved.
This guide explores seven different deployment options, ranging from simple but not-so-scalable techniques to significantly more complex yet highly scalable approaches:
For each option, we discuss the limitations of the approach, why you might choose it, why you might not, and (where appropriate) how to mitigate some of its potential downsides.
This guide also covers some hurdles you may encounter as you begin using the more complex techniques, deploying changes other than metadata, the various Salesforce environments involved in moving changes to production, an example deployment that combines multiple approaches, and third-party tooling you can use.
You can read this guide straight through, or just jump to the parts that you need. If you do decide to skip around, we’ve summarized the key points that you’ll want to take away with you no matter what:
This guide focuses on moving changes between environments with the goal of eventually deploying to a production environment you control. In other words, if you’re a customer or developing changes on behalf of a customer, then this guide is for you. If you are an ISV or AppExchange partner who is building assets for multicustomer or AppExchange distribution, then you should follow the documentation for second-generation managed packages.
First, let’s get familiar with the deployment options and the technology behind them.
Manual | Change Sets | Metadata Deployments | Packages | ||||
---|---|---|---|---|---|---|---|
Direct | Single Source | Org-Dependent1 | Unlocked | Managed | |||
Deletion | Manual | Not Available | Manual, Scripted | Manual, Scripted | Built-In | Built-In | Built-In |
Apex Changes | Not Available | Available | Available | Available | Available | Available | Available |
Reversion | Manual | Not Available | Manual | Manual | Built-In | Built-In | Built-In |
Scratch Org Support | Supported | Not Available | Supported | Supported | Supported | Supported2 | Supported2 |
Sandbox Support | Supported | Required | Supported | Supported | Supported | Supported | Supported |
Dependencies | Any | Any | Any | Any | Any | Packaged3 | Packaged3 |
Repeatability | Low | Low | Medium | High | High | High | High |
Delay | None | Medium | None | None | Medium | Long4 | Long4 |
As you move from left to right on the spectrum, you:
For the purposes of this document, scalability means support for:
Deletion | Apex Changes | Reversion | Scratch Org Support | Sandbox | Dependencies | Repeatability | Delay | |
---|---|---|---|---|---|---|---|---|
Manual Changes in Production | Manual | Not Available | Manual | -- | -- | Any | Low | None |
The simplest option for deploying to production is to make a manual change, directly in production.
Yes, some of you just had a panic attack. But hear us out.
You cannot modify Apex code in production. You must write Apex somewhere else and migrate it to production. If your project involves only Apex, then move along, this is not the option you’re looking for.
>
instead of <
can bring your company to a halt. Even worse, your automation might accidentally email customers and create a PR mess.If you have changes that can only be done manually, then you can verify them by first completing the steps to make the changes in a sandbox, testing the results, and then repeating the same series of steps in production.
For example, Prediction Builder currently (Winter ‘21) doesn’t support any sort of deployments other than manual. Prediction Builder lets you configure a model and look at its accuracy. You can tweak the model until you’re happy with it.
But eventually, you’ll have Einstein start writing predictions to fields, and you may start using those fields for process automation. Before that starts, you might want to test how it works in a sandbox. Once you’ve done that, you do have to create and enable the model again in production (for example, with production on one monitor, sandbox on the other, carefully making them match). This approach is not foolproof, but at least when you move to production, you’ll sleep more soundly.
Deletion | Apex Changes | Reversion | Scratch Org Support | Sandbox | Dependencies | Repeatability | Delay | |
---|---|---|---|---|---|---|---|---|
Change Sets | Manual | Supported | Not Available | Supported | Supported | Any | Low | Medium |
Change sets are a point-and-click way to move changes.
They let you choose which items to move, with a checkbox for each field, object, layout, class, and so on.
The org admins can decide which environment can send and receive changes sets from other environments via deployment connections. For example, consider the following scenario:
Once you make your selections with all those checkboxes, you “upload” them to an allowed destination org. Some time later, the change set appears in Inbound Change Sets in the destination org and you can deploy or validate the change set.
If your team has been using change sets, but is considering moving to source-based deployments, there is an option to retrieve change sets via the Salesforce CLI. This enables you to create a change set from your sandbox. Then a CLI user or a script can retrieve the change set by name using the CLI retrieve command and extract the source (give the command the change set name as the package name). In this case, you’re not really using change sets for deployment, but are using them to extract source to enable a deployment technique further to the right.
Deletion | Apex Changes | Reversion | Scratch Org Support | Sandbox | Dependencies | Repeatability | Delay | |
---|---|---|---|---|---|---|---|---|
Metadata: Direct Deployments | Manual, Scriptable | Supported | Manual | Supported | Supported | Any | Medium | None |
The Salesforce Metadata API lets you migrate metadata. Few people use it directly — if your process has been around for a long time, you may have used Ant scripts. More recently, the Salesforce CLI
and Salesforce Extensions for Visual Studio Code
and many other tools make use of the metadata API to retrieve and deploy metadata.
Scenarios here include a developer retrieving metadata from a sandbox, making changes on their machine, and deploying it back to production.
You can also perform deployments that look like, “take the metadata described in this package.xml(the traditional Salesforce manifest file) and move it from QA to Production.”
In metadata-based deployments, you’re adding or modifying only what’s specified. The deployment doesn’t delete or change any files that are omitted.
Companies tend to have a single person who has access to make these deployments (e.g. a “Release Manager”). While this helps ensure control, it can become a bottleneck.
Deletion | Apex Changes | Reversion | Scratch Org Support | Sandbox | Dependencies | Repeatability | Delay | |
---|---|---|---|---|---|---|---|---|
Metadata: With Source Control | Manual, Scriptable | Supported | Manual | Supported | Supported | Any | Medium | None |
Most developers are comfortable working with a source control system (also referred to as a version control system or VCS), like git. Such systems have all sorts of useful features (like branches, pull requests, diffs, file history, and more). Source tracking is a solved problem with high-quality tooling outside of Salesforce, and we recommend using it.
Back to deployments — the idea here is to use source repository branches as the source for a deployment. Developers are prohibited from deploying source directly beyond their dev environment; only by merging into a branch does their code deploy anywhere else.
Typically, these branch merges are deployed by a system (e.g. CI) rather than a person. The steps are:
Because the Metadata API and CLI are available, you’re free to use the tools you prefer. For example, GitHub acts as a source control system but also handles things like code review, and GitHub actions support automation based on events (like merging a branch).
When you begin using this deployment option, you may find yourself facing some challenging questions. What do my repos look like? Am I always deploying the whole thing, or is there some subset of metadata? Do I have one repo with one directory, multiple package directories in a single repo, or multiple repos? Multiple projects within a larger monorepo? How do I express and control dependencies between them? This challenge is not exclusive to this method; you’ll be addressing the same questions when you begin moving to packages.
There’s some preliminary discussion about modularization on the Developer blog, but it’s a few years old. In particular, it doesn’t account for some newer options like Org-Dependent Packages that help with this problem, and the CLI is now much better at working with multiple source directories within a single project.
See Limitations of Direct Metadata Deploys.
The next three deployment techniques dive into Second-Generation Packages.
Salesforce has used packages since the launch of AppExchange, and most admins are familiar with installing managed packages into their orgs. First-generation managed packages were designed primarily for this ISV use case. Managed packages are very restrictive; once you release a package, there are many changes that are no longer allowed because the developer can’t know what a customer org may have built dependencies on. There were also some customers using unmanaged packages, which were impossible to upgrade.
We recommend not using at first-generation managed packages, also called Classic Packaging, at all. If you’re not an ISV currently using them, you have no reason to start now. Second-generation packages are where it’s at: managed packages primarily for ISVs and unlocked packages primarily for customers.
Second-generation packages are created from source, and not from the contents of an org. The naming of the various kinds of packages can be confusing and hasn’t been consistent over time. In this guide, unless we’re speaking of first-generation managed packages, we’ll drop the “generation” label and refer to packages as unlocked or managed.
Note: This also follows the naming you'll see used in the Metadata Coverage Report
, as well.
The idea of a package is to have a subset of metadata that is versioned.
Packages also offer some deployment controls. When you create a package version, the version begins in Beta status. You can install the package in scratch orgs and sandboxes, but not in a production org.
To deploy in production, you must first promote a package to released status. By controlling that phase, packages enable easy distribution for testing but a formal, controlled release.
The next three sections describe package types.
Deletion | Apex Changes | Reversion | Scratch Org Support | Sandbox | Dependencies | Repeatability | Delay | |
---|---|---|---|---|---|---|---|---|
Org-Dependent Packages | Supported | Supported | Supported | Supported | Supported | Any | High | Medium |
Org-dependent packages are technically unlocked packages with a special flag (—skipvalidation
) during creation. They allow dependencies outside of the package that aren’t in another package — in other words, they depend on something in your org.
For example, let’s say you’re building a package that includes a Flow, and that Flow refers to a custom notification type (NotificationTypeConfig). That metadata type is supported in the Metadata API as of Winter ’21
but it can’t be packaged. When you review the Metadata Coverage report, keep in mind that org-dependent packages are unlocked packages. The supported types will be the same.
An org-dependent package lets you package your Flow and optimistically assume that the Custom Notification Type will be present in the destination org. It’ll throw an error on installation if that Custom Notification Type is not present.
You’ll want to use a sandbox that supports source tracking so that
Whatever__c
deployed to it. If you deploy a package that includes Whatever__c, then that metadata will be recognized within the org as being part of the package from then on regardless of how it was originally deployed.Deletion | Apex Changes | Reversion | Scratch Org Support | Sandbox | Dependencies | Repeatability | Delay | |
---|---|---|---|---|---|---|---|---|
Unlocked Packages | Supported | Supported | Supported | Supported | Supported | Packaged | High | Long |
If you’re a customer using packages, unlocked packages should be your primary deployment option. Unlike org-dependent packages, unlocked packages have all dependencies either inside the package or inside another package explicitly declared in the package’s dependencies
Unlocked means simply, “allows changes not via the packaging process.” For example, imagine you’ve packaged a formula field that’s causing problems. An unlocked package allows you to modify the formula in production! You can put out the fire immediately.
But next time you deploy the package, whatever is in the source will deploy over any changes made in production; that is, whatever is in the package wins. The only way to make a permanent change is to remember to update the formula in the package so that subsequent deployments include the fix.
Salesforce previously announced a concept of locked packages, which were less strict about changes than managed, but didn’t allow manual changes in the org. This has been deprioritized.
For packages intended for non-production environments, you can skip the package validation step. This speeds up the packaging process so you can deploy and get test results sooner. If you’re using automated tests and frequent builds, this can be useful.
You’ll still eventually need to validate the package and promote it before you deploy it to production.
Deletion | Apex Changes | Reversion | Scratch Org Support | Sandbox | Dependencies | Repeatability | Delay | |
---|---|---|---|---|---|---|---|---|
Unlocked Packages | Supported | Supported | Supported | Supported | Supported | Packaged | High | Long |
The workflow for this option is the same as Unlocked Packages, so that diagram is omitted here.
Managed packages have more limitations than unlocked packages. They’re normally used by AppExchange partners who want to prevent customers from creating dependencies on code or components that aren’t designed to be depended on.
There are a few common constraints to moving to the right on the spectrum.
Metadata and packages require teams that have some familiarity with code and source control. Use of the Salesforce CLI is recommended, as is Visual Studio Code and the Salesforce Extensions. Even experienced Salesforce admins and developers may not be familiar with the latest tools. From an individual user’s perspective, the extra steps may feel like more work because it’s not always easy to see the eventual big-picture gains.
Scratch orgs and sandboxes that support source tracking make it easy to retrieve what you’ve changed in an org. The Salesforce Extensions for VS Code make it possible to easily retrieve those changes (via shortcuts) and built-in GitHub integration means you don’t have to use the CLI, either. Even developers who adore terminals benefit from how few keystrokes this requires.
The new Salesforce DevOps Center, currently in Developer Preview and planned for GA in 2021, will help admins work with source-controlled deployments. It offers a simpler way for non-developers to make changes in a developer environment, automatically track those changes (no spreadsheets for building change sets!), and commit them to source control (no IDE or CLI!). Join the Trailblazer Community Group for DevOps Center
to stay informed.
Assuming people are willing to learn all these new tools, there’s the issue of tooling and access itself. For example, some companies restrict installation of developer tools on machines. You may have to get exceptions to software restrictions, ports unblocked, a public npm registry allowed, and so on.
And while we take for granted cloud-based source control (e.g., GitHub and GitLab) that may not be an option for some companies. The setup described below may involve several on-premises servers and be more complex than most of us experience. Or, your company may require a security review of the cloud services you choose.
Not everything can be deployed by every technique due to product gaps. The best resource for understanding these gaps is the Metadata Coverage Report. The following images and scenarios are as of Winter ’21 (api version 50) and subject to change.
For example, let’s say you’ve set up and tested LiveAgent (Chat) in a sandbox. To move that to production, based on the chart above, you could:
You could not use a package to do the deployment.
Note: There are more objects related to deploying LiveAgent. We simplified this example so you don’t have to scroll all over the Metadata Coverage Report to look at all of them.
If you can’t find what you’re looking for on the coverage report, for example predictions built with Prediction Builder or portability policies, then they aren’t supported in anything other than manual setup.
Why doesn’t everything support all the deployment options?
This is almost always a prioritization challenge. Products are built by teams and owned by a product manager who has to prioritize what their users want. Each team is responsible for adding support for deployment techniques to their product, and they balance this against new features, bug fixes, and other work.
If you are using a feature that doesn’t deploy well, reach out to the product manager to make sure they know that you value deployability.
Your process may dictate product adoption
Eventually, you may have an amazing deployment process you love that’s running like a well-oiled machine. Then, Salesforce creates some killer new feature that your users are really excited about, but it lacks support for your preferred deployment process.
At this point, you face an uncomfortable choice: Create a whole new process around deploying that one tool (adding complexity and reducing agility), or wait until the new feature has proper deployment support that lets you preserve your process.
Ultimately this becomes a “greater business value” choice. This is another scenario in which it’s important that the product team understands that their deployability support is preventing your adoption of their feature.
Continuing the previous example, imagine you have additional functionality that depends on your LiveAgentButton (think of an Experience, formerly known as a Community, where that button is embedded). You would also not be able to use unlocked or managed packages for that community (ExperienceBundle), even though ExperienceBundle itself works with unlocked packages, because the ExperienceBundle package wouldn’t contain all the source without that button.
You could, however, use an org-dependent package that assumes the button will exist in the target environment.
As you look through the coverage report, you’ll see links to known issues. Second-generation packaging is relatively new, as are the SFDX tools and features like Code Builder and DevOps Center.
Additionally, Salesforce is making huge efforts to expand metadata coverage and releasing new products and features. You are more likely to find blocking bugs and gaps in newer functionality.
You may even find that within a metadata type, certain features don’t behave as expected. For example, orgs with source tracking will register changes when adding a new field or renaming an object, but changes to an object’s field history tracking are ignored. You can edit the object metadata by hand to change the value, and then it deploys as expected.
Please report issues so that Salesforce gets them fixed and other customers are aware of them.
OK, so let’s say you’ve chosen one or more options described in this guide for your project. You’ll typically find “other stuff” that you need to deploy with your change. Here are some examples:
In these examples, if you’re doing manual deployments, these are just additional manual steps.
If you’re using packages, you have the option to create Apex classes that run as a post install script. They can verify the state of records in the org and modify where necessary. There is no option to do a pre-install as part of the package installation, so you’ll need to make those changes manually or from a script outside the package.
If you’re doing deployments from metadata, you’ll need to complete these steps either manually or via a script that runs before and/or after your deployment.
Manual | Change Sets | Metadata API Deployments | Packages | |
---|---|---|---|---|
Pre-Deploy | Manual | Manual | Manual, External Script | Manual, External Script |
Post-Deploy | Manual | Manual | Manual, External Script | Manual, External Script |
The advantage of using deployment scripts is testability. You can run the script on a non-production environment and verify the result, and modify the script as necessary before using it in production.
Permissions are worth a special call-out. Historically, when people create new objects, fields, and so on, they often assign them to one or more profiles. With change sets, it’s possible to deploy those profile changes.
The scenario get a little more complicated with metadata deployments. You can modify a profile and retrieve it from a source-tracking org, but it’s going to be the entire, very large profile instead of just what you’ve added. The metadata API tries to handle these modifications for you and may be successful. For example, if you retrieve from a change set or package.xml, the API will try to return the portion of the profile that corresponds to the other metadata in the retrieval scope. Similarly, you can deploy a profile that contains only what’s in your package and the API will attempt to merge it with the existing profile that covers the rest of the org. You probably want finer-grained control than that.
Packages are even more interesting. On deployment, they assign (by default) permissions for everything in the package to the System Administrator profile. If you ever retrieve that profile, it’s going to have references to all the installed packages.
If you’re using an org with source tracking to build, adding any object or field to a profile will cause the profile to be marked as “modified.” When you retrieve the source, the entire profile downloads, not just the field you change. The profile source probably refers to something in the org beyond the scope of your project, so you’ll be manually cleaning those to keep from polluting the profile source files.
You likely see the point: Profiles are not the right tool. Salesforce recommends using permission sets to assign permissions. They’re more granular, aren’t 1:1 with users, and eliminate dependencies on a profile. If you’re not familiar, take a moment to read Migrating to Permission Sets for DX. You can also use permission set groups
to reduce the work of managing common clusters of permission sets.
Once you’ve moved beyond manual changes in production, you’re into the world of developer environments. This section covers the different types of environments available to you and how we recommend using them.
A sandbox is an org that’s created from your production org and remains connected to that org. Usually, the metadata matches the production org’s metadata at the time of sandbox copy. It is possible to copy a sandbox from another sandbox.
Your sandbox allocation is based on the edition of your production org. Salesforce will sell you more if you need them.
Sandboxes can be deleted or refreshed (a fresh copy from production) but are limited in the frequency. The minimum duration in the table below describes how long a sandbox must be active before it can be refreshed or deleted.
Sandboxes | Scratch Org | ||||
---|---|---|---|---|---|
Developer | Developer Pro | Partial Copy | Full | ||
Data Storage1 | 200MB | 1GB | 5GB | Matches Production | 200MB |
File Storage | 200MB | 1GB | Matches Production | Matches Production | 50MB |
Minimum Duration (Days) | 1 | 1 | 5 | 29 | None2 |
Data Copy | None | None | Per Template | Per Template or All | None |
Metadata Copy | Matches Production | Matches Production | Matches Production | Matches Production | None |
Features/Licenses | Matches Production | Matches Production | Matches Production | Matches Production | Matches Definition File3, Shape4 |
1 Salesforce has an unusual way of calculating storage based on record count.
2 Scratch orgs have a maximum duration of 30 days.
3 Scratch org definiton files allow for various feature enablements and license configuations.
4 Scratch org shape (Beta) allows scratch org feature and license enablements to match a source org.
The main difference between Developer and Developer Pro sandboxes is their storage capacity. You should use them for creating most changes. Because they support source tracking, you can use the CLI or DevOps Center to capture your changes for you. Once you’re done with changes, you can migrate those changes as described in the Deployment Techniques, from Simplest to Most Scalable section.
The challenge with these sandbox types is that they contain no data when created. As a result you need to do one of the following:
Partial Copy sandboxes allow for more storage and let you create a sandbox template to copy a subset of production data. This dramatically simplifies the data set up and can be used for complex testing where a lot of test data is required.
The main limitation of templates is that they work per object. If you have a small amount of production data, you can pick the objects that you want. But if you need Person Account records, but have 3 million of them in production, you can’t select which Accounts/Contacts the template should copy; it’s all-or-nothing at the object level. Because each Person Account is 4k of storage (one account at 2K plus one contact at 2K), 3 million of them will consume about 11GB of data storage.
A full copy can be exactly what it sounds like — just copy everything. Because sandbox copy time is related to the amount of data to copy, you can limit the copy to the items you need using a template. Besides data, you can also choose to include or omit things like field history and Chatter to speed up the copy process.
Full Copy sandboxes are best suited for:
During Salesforce releases windows, you will want to carefully time your sandbox refreshes to make sure sandboxes are on the version you want. The dates can change each release, as well as which instances receive the release preview before or after production, so always check the release information.
You might want some developer sandboxes to remain on the same release as your production org for scenarios that involve hot-fixes or debugging.
At the same time, you may be working in Developer sandboxes on a project that should go live after the next Salesforce major release. There, you’ll want those orgs on preview so that you can test against the target release and use any features in that release that aren’t currently available.
There may be a period where you can’t promote certain changes from your preview sandboxes until destination orgs receive the release.
You may wan to use another sandbox to prepare for releases with user training, creating release documentation, or similar activities.
Sandbox planning requires keeping up with the release dates for not only production but also specific sandbox instances and planning refreshes around release windows.
About those copy times
Sandbox copies on a large org can take several days. Large orgs will want to plan accordingly if they really need everything in their org in a Full Sandbox.
Salesforce has announced Quick-Create Sandboxes (both Developer and Full) that dramatically reduce the copy time—a large org might copy in less than 10 minutes instead of days. Not only does it reduce the wait time when users manually create sandboxes, but also allows for more automation in CI processes. This will be especially useful when changes can’t be packages or when using Org-Dependent packages.
A Developer Preview for Quick-Create Sandboxes may occur in the Spring ‘21 release.
Sandboxes do copy your users from the production org, including their permissions. If your sandbox owner is an administrator in production, their sandbox is ready to go — they can do what they need to.
Some companies either limit developers’ privileges in production or don’t allow developers a production login at all. If that’s the case, someone with production admin permissions will need to create the sandbox, log in, and then elevate the permissions of the sandbox user to whatever is required for their changes (usually full permissions).
For sandboxes that copy from production data (Partial Copy and Full Copy types), or for organizations that are copying production data to Developer or Developer Pro Sandboxes, this opens another potential security problem. Specifically, there may be production data developers should not have access to. Besides access by the developers themselves, developers may make changes to security policies or open temporary security gaps. Some examples:
This risk is mitigated by using a tool that masks production data like Salesforce Data Mask. The Production Administrator can decide which data should be obfuscated or deleted as part of the sandbox creation process to prevent developer access or inadvertent exposure.
Scratch orgs are very different from sandboxes. They are meant to be created quickly, destroyed quickly, and be more configurable.
An example of configurability: Let’s say you want to experiment with a new feature like Salesforce CPQ. Sandboxes will create with the licenses, configuration, and metadata from your production org. You’d have to get CPQ licenses added to production, then create your sandbox (or sync licenses of an existing sandbox).
But with scratch orgs, you can specify the org’s features in a configuration file. You can spin up the org and do your proof-of-concept.
For developers building features, scratch orgs help with enforcing dependencies. Because scratch orgs don’t start with your production metadata, you’ll be able to capture in source control everything your changes require. If you forgot to include something, you won’t be able to deploy it to a scratch org.
Scratch orgs are the preferred option for creating non-org-dependent packages. And behind the scenes, they’re where Salesforce builds your package from your source.
For some customers, the complexity of configuring and scripting the set up of scratch orgs has been a barrier to their use. They really are empty unless you specify the configuration, settings, metadata, and data.
To make this process easier, scratch org shapes (Beta in Winter ‘21) provide two options:
Additionally, building scripts for scratch orgs are another challenge. First, you have to create and maintain the scripts. This can be especially challenging for users without shell-scripting experience. Second, they can take a long time to run, especially if you’re installing a lot of packages (your own or AppExchange).
To accelerate this experience, there’s a pilot for scratch org snapshots that let you get an org to a known state (for example, installing all the packages and doing data setup) and then store the snapshot of it. Then, future orgs can start from that snapshot.
Remember, most companies can’t (or shouldn’t) use a single technique for all deployments.
The following is a realistic scenario of a company trying to move to a packaging approach while running multiple techniques.
In this scenario, you want to use packages because you have a complex enterprise environment where several teams (both internal and SI) are working on multiple projects that eventually deploy into a single org. Occasionally, these separate teams come into contention on shared objects like Account and Contact.
Where you can’t use packages, you do metadata deployments from source (at least for now), and you have one project using its own process due to Salesforce limitations within specific features.
Several parts of your org’s configuration are currently deployed using Unlocked Packages. This is your preferred option when possible. Any changes run through your CI process, create a new package version, and deploy. Each package contains a few permission sets that are sometimes modified, too.
With this approach, you may experience...
Additional metadata exists in a single large GitHub repo per Metadata API: Deployment with Source Control + CI. You’d like to break part of it off into a few more packages, but haven’t had time yet. It’s not clear how it should be organized in a package because the dependencies are so tangled. You use GitHub Actions to deploy this between environments. Some parts of it probably end up being Org-Dependent Packages eventually, but you don’t like using non-GA features.
integration
branch.Integrate
to verify and run larger tests.QA
branch, which initiates a metadata deployment to a Full Copy sandbox. Users can test larger changes there.main
branch, which deploys to production. This is a lot of manual merges and a complicated branch operation, but does allow for granular changes to go when they’re ready. It may also create a lot of manual reviews in the QA sandbox.With this approach, you may experience...
You have an Experience using Salesforce CMS that you work on in a Full Copy sandbox. You’ve had bad Experiences (pun intended) moving these via metadata because of product gaps and bugs, so you typically build LWC for the community in the full sandbox, deploy them to production via Metadata API containing just the LWC and supporting Apex classes, and let the experience administrators manually add them to the production version of the Experience rather than try to deploy the Experience. This entire process is owned by a single developer.
With this approach, you may experience...
The SFDX command line tools are agnostic to your source, and the use of scripts should let you work with the tool of your choice.
Early iterations of DevOps Center work with GitHub, so if you can use that for source control, you should.
CumulusCI is a free, open-source CI tool used heavily by the Salesforce.org
ecosystem (not-for-profits). Support for second-generation packaging is in progress, so we do not recommend using its default automation unless you’re an ISV.
However, it is extensible to use any Salesforce CLI command (or any shell command in general). It includes some powerful features for automating UI tests (simulating a browser), loading test data, creating fake data, dealing with namespaces, and managing releases and release notes via GitHub.
Several tooling vendors are working to solve some of the complexities of deployments. You should explore them as part of any company-wide deployment strategy initiative.
Someday, API support may be so ubiquitous that you can select deployment mechanisms solely based on your team’s preferences. Until then, the Metadata Coverage Report is your friend.
Give it a look anytime you’re planning to move rightward on the spectrum or introduce new metadata types into your deployments.
Help us make sure we're publishing what is most relevant to you: take our survey to provide feedback on this content and tell us what you’d like to see next.