Nothing is more permanent than a temporary solution. It’s why the software keyboards on our touchscreen smartphones are laid out in QWERTY. Why fax machines are the preferred means of transferring medical records. Why, when traveling the world, you must take great care in how you go about powering your American electronics, lest they meet an untimely end at the hands of 220-volt electrical infrastructure. In the corporate world, this phenomenon plays out daily in unexpected ways. Given enough time and neglect, a spreadsheet macro meant to calculate holiday paid time off becomes a mission-critical feature for the entire Human Resources department. In history and culture, these strange origins and offshoots and curios are a simple fact of human nature. In business, it’s also a fact of life, but if not accounted for correctly, it becomes something known as Technical Debt.
Technical debt is the idea that too narrow of use cases outlined in a design will only create new problems in the future when you attempt to expand the functionality. In simpler terms, cutting corners only saves time and money in the short term as it rarely scales — a philosophy familiar to anyone who has asked or been asked to “move that button on the screen over to this other page” or “make the site banner say something different on weekends”. The response being, “That sounds simple, but with the way it was designed, we’d have to rework the entire code base.” Much like Rutger Hauer, developers have seen things you people wouldn’t believe.
Technical debt works like any other debt when left unchecked. It weighs you down and makes any future decisions far more complicated. For a business, unlike Hauer, these moments are not lost in time, like tears in rain. Instead, they pile up until one day it becomes too costly to ignore. That’s when the rework happens, and hopefully, the technical debt is paid off with thoughtful design instead of kicked down the road for the next project to solve.
Technical debt is the idea that too narrow of use cases outlined in a design will only create new problems in the future when you attempt to expand the functionality.
I say all this as a preface to talk about a very specific feature within Salesforce. No one tool or feature or product fully resolves technical debt, but anything that aids in design that avoids it should be something evangelized in any project. Specifically, I’m talking about Custom Metadata Objects. Obvious and maybe even laughable to some, maybe. Critical that it at least be understood and considered.
Custom Metadata in Salesforce sounds a lot more complicated than it is. It works similarly to regular Custom Objects in that one houses records with customized attribute fields. The key difference resides in the fact that Custom Metadata lives behind the Setup region of Salesforce, a place for system admins and developers rather than your standard sales user. As far as regular users are concerned, these records do not exist. They operate behind the scenes, the stage crew rather than actors. Yet it remains accessible to queries in code, as easy to see for developers as any other records in the system. This is by design.
Imagine, for a moment, your business has a burning desire for a Project record to be created whenever an Opportunity is Closed Won. Easy enough, automatically creating records when another record is updated is a long-established mechanism within many organizations. However, there is also a dependent requirement to create related Milestone records under that new Project record at time of creation. (Milestones in this instance are just smaller pieces of a Project, allowing to track the minutia of its progress) Further complicating the design, the number and names of Milestones that need to be created depends on the category of Opportunity being closed. The most direct (and awful) approach to solving this would be to lay out the different types of Opportunities and their resulting Milestones in the code itself. “Hard coded” is the term for this, and it should be avoided.
What if a new Opportunity type is identified and needs to be implemented? The developer would need to dive back into that code to make a change. What if the Milestones would need to be tweaked? Again, a developer would be responsible for making that change. How often would these changes need to be made? No doubt, the difficulty in changing this design over time would even discourage attempts to change it in the first place. Not a very flexible solution by far!
A better solution would be to expose those requirements as configuration tables. This is a long-established best practice across many industries. If you have ever found yourself changing the difficulty or graphics settings in a video game, you have interacted with one of these tables. Program startup settings. Disabling the auto-play preview feature on a streaming service. None of these require any familiarity with programming languages to make changes, nor should they. That’s exactly the type of mindset that should go into designing something within Salesforce as well.
With Custom Metadata, the approach should be to expose anything that could be considered “configurable” as records. In this Project/Milestone example, each record would be a milestone. Their attributes would denote what Project Type they correspond to, what each Milestone would be called, and any other aspects that the business would deem necessary. From there, the code’s job would be to look at the Custom Metadata records, filter down only to the relevant ones based on the current Opportunity, and then iterate through the list. The end result is a Project and a series of related Milestone records created behind the scenes, automatically for the user as if magic.
Should the business decide that new Milestones are needed, it would only be a matter of editing or creating new entries in the Custom Metadata. This is something anyone with admin access could do easily, with no additional coding required. As a result, the process can be tweaked and refined as needed over time with little technical involvement.
With Custom Metadata, the approach should be to expose anything that could be considered “configurable” as records.
This is just one example of what could be done with Custom Metadata. Comparison charts, regional grouping tables, the sky is the limit. On a technical level, Custom Metadata also bypasses several bandwidth restrictions imposed on normal custom objects. I won’t go into detail here, but essentially, it’s a good place to put stuff that you expect to be accessed in high quantity with a low level of non-admin modifications. And as mentioned before, it’s not the ultimate panacea to technical debt and design woes, but yet another tool in your belt. Having the right tool for the job does wonders.