The Dos And Don’ts Of Managed Packages

When it comes to managed and default packages, if you don’t set it up correctly, you don’t follow ‘the rules,’ or you remain inflexible to change, your organization could go up in ‘flames.’

The Dos And Don’ts Of Managed Packages
Table of contents

That’s why this article will build its way through the dos and don’ts of managed packages.

What you need to know about managed packages

ISVs (Independent Software Vendor), multi-org companies, and builders seeking to share their solutions will likely meet managed packages on their trail to distribute products to end users.

A managed package’s upgradability provides distribution benefits over unmanaged ones.

Unmanaged packages have uneditable component qualities, which can cost the team working behind the scenes to maintain a healthy organization time, money, and frustration.

With managed packages, you’re ready to grace the cloud with features that optimize and simplify your end user’s daily work.

However, keep in mind that Salesforce-managed packages are constantly evolving, and there’s much to consider when deciding between first-generation (1GP) and second-generation (2GP) managed packages.

The Dos

Use second-generation packages

Salesforce released a new way to create and distribute solutions with 2GP. The generation was designed with modern development teams in mind with a source-driven and automation-friendly development model. The model is fully executable via Salesforce CLI (Command-Line Interface).

As 2GP catches up and makes future improvements, the focus will be on this new generation.

Build with flexibility in mind

Salesforce apps will always be affected by change – many of which come from external factors we can’t control. New user requirements, software trends, and updates to Salesforce can lead to changes in architecture, design, and code for a development team. There are also configuration changes for your customer’s implementation team.

Designing your product to manage change will set you apart in the long run as development teams need to pivot.

On the other hand, admins need to customize their implementation for the organization’s unique needs and for when the next Salesforce release comes out with new and improved features that your app can leverage.

It’s also important to remember how people and processes also make an impact. You have to plan for the following:

  • Changes with release schedules
  • Team retros
  • Salesforce release note reviews.

Routine user surveys can help you stay ahead of the uncertainty of your products' current environment.

Prioritize flow and invocable actions over triggers

While Flow can’t solve everything that triggers cover, they offer flexibility. Flow enables a customer to troubleshoot, deactivate, and customize the automation they package. Flow is significant for automation on standard objects where a customer’s automation project setup is out of their control.

Your automation code may work on one organization, but combined with the triggers, Flow, and validation rules could lead to errors.

Managed trigger code is hidden and uneditable, making them hard to debug and impossible to deactivate. Trigger code brings more headaches for orgs that implement trigger frameworks requiring custom boilerplate code.

Flow becomes more powerful with every release, and invocable actions add Apex access for more complex operations. We recommend considering them first for all automation you need to package and to make your Flow overridable.

In a best-case scenario, they become a toolkit for your customers’ admins and a solution architects can use to tailor your app for their specific needs.

Include an internal API to access your package's business logic

One of the most exciting things about having an app in customers’ hands is seeing them use it in innovative ways you never imagined. A thoughtful and flexible approach to enabling this is by exposing bits and pieces of your business logic to be sequenced and triggered in new combinations.

We suggest leveraging Salesforce’s custom object or platform event structures to design an ‘API command’ object, callable via a record or a platform event-triggered Flow. Essentially, your apps can have more ways to run actions than through a custom activity feed UI.

Incorporate translatable labels for custom UI text

While most Salesforce customers are from English-speaking languages, we recommend ensuring your app welcomes international users by replacing any hard-coded text in custom UIs with labels.

Packaged labels can be imported into Visualforce, Aura, and Lightning Web Components and translated into Salesforce’s standard custom label UI.

Package permission sets and permission set groups for your features

Salesforce’s shift to focus on permission sets over profiles for internal controls works favorably for managed packages. Instead of creating packaged profiles to update your customers’ existing ones – or require them to provide access to your features manually – you can create permission sets that grant access at different levels of granularity.

Use permission set groups (or a command prompt) to create template permission collections and give your customers ready-to-use starting points. By combining both, you provide flexibility and convenience.

Provide help and description text for your custom fields

Even with a fully custom UI, users are bound to use data points from your app in a list of package views, reports, formula fields, custom automations, and more.

Include descriptions and help text for all of your custom fields to eliminate the need to read documentation or contact support. Admins, data analytics, and developers will thank you.

Create a description of your post-install scripts' steps

Installing scripts saves time for an admin and encourages your end customers to use your app sooner. However, they are a ‘black box,’ making it hard to understand the changes they make and troubleshoot them if an error occurs.

A simple document that summarizes your post-install script’s steps will guide your debugging along the way. This document will help an admin run your app in a complex org – and reduce the back-and-forth between customers and support and customer success teams.

Design a custom UI admin panel

Custom configurations with Salesforce often mean opening multiple tabs to click between setup pages and subpages and testing their effects. Every organization has a web of configuration dependencies, and the accessible components in the managed package file type add another layer.

Package type your development team’s expertise about your app’s dependencies into a central guide that includes knowledge and links to all configurable aspects of your app.

Remember that your app is likely one of many additional packages in a customer’s organization – giving an admin a reliable place to go when they need to change.

The Don’ts

Don’t use too many post-install steps

Before an end user sees your app, it must pass through a likely busy and spread-thin Salesforce admin. Larger companies can rope in ‘success engineers’ to handle post-install work for their customers, but smaller ISVs must build trust with the admins who need to do the dirty work.

Admins are used to post-install steps for managed packages. They know a simple install without any vulnerability issues is rare for Salesforce organizations.

So, if your post-install guide is longer than a page and requires clicking through more than five different setup pages, setting up your app for end users may further down an admin’s backlog.

Invest in developing scripts that automate manual steps via the package metadata type and tooling API. Then, you can collect post-install needs on the main Lightning page, which guides an admin through the process.

This influential group of trailblazers and innovators will appreciate a brief and concise experience with the necessary custom settings.

Don't modify organization records in install scripts

Customers understand when solutions need to enrich their organization’s data. For instance, adding geolocation coordinates for map visualizations or setting vague search terms for improved duplicate matching.

Those relying on record history data would not be happy if your app implemented these enhancements in an install script without getting consent or at least being upfront about the upcoming changes.

Every customer has a different set of automations that may fail at scale, and updating ‘last modified’ fields risks cluttering data hygiene or audit trail reports.

As fundamental as modifying customer records may be, it is rather suggested that these processes be packaged as source code that admins can choose to run when they know of the side effects and have, in turn, prepared their system.

Don't package standard actions and page layouts with the native labels

This point may seem like a no-brainer, but it can also be overlooked when packaging complex solutions that include standard objects. Many admins have encountered managed packages with everyday global actions repackaged without explanation.

Salesforce’s Lightning record page configuration UI does not include namespaces when adding actions – this information only appears on hover for the page layout UI. Using native labels may adhere to Salesforce’s jargon, but it confuses an admin looking to add the proper action to a page.

In most cases, if you’re packaging an action, it’s for an app-specific reason, and it should be labeled as such for those configuring and using your solution.

Don’t use global methods (unless absolutely needed)

Global methods are a way to expose your app’s business logic to an end customer’s development team. There is a lot of potential customization power with global methods. However, they also come with many risks, errors, and hazards.

Global methods can not be deleted from a managed activity package, and their signatures can’t change. These methods make it difficult to change old code to new requirements. On top of this, as Salesforce features come about, this can lead to technical debt that can’t be thoroughly cleaned up.

Consider exploring all the options with custom objects or platform events to access your package’s business logic. We recommend using global methods only as a last resort for cases like implementing a custom REST (Representational State Transfer) API endpoint or when code outside the package needs to be called.

If you need to use them to maintain flexibility for your development team, implement your method’s parameters using map objects that add extensibility by adding more fundamental values.

Take caution when exposing Lightning Web Component (LWC) attributes

Design attributes for Lightning Web Components (LWC) allow admins to customize tools for your organization’s needs. While this can multiply the use cases your components can solve, flexibility for the admin needs to be balanced with the rules of managed packages. Two important rules to keep in mind are:

  • Once the property, "isExposed, "Once the property "isExposed" of an LWC is set to true, it must stay that way. This is to avoid lengthy support cases with Salesforce to try to get an unwanted property removed
  • An exposed component’s “targets” and public “api” properties can not be removed. This also includes "target" and "api" properties added after the component is exposed.

Full documentation about the fixed nature of these properties is available here.

You can check out our article on extending managed packages to learn more about this.

Go ahead and build your business with managed packages

When creating a managed or unlocked package, you do more than offer a solution for the end customer. You’re asking them to join a complex and evolving ecosystem orchestrated by:

  • Admins
  • Developers
  • Architects
  • Product owners
  • Analysts
  • Power users.
As the saying goes by Kamand Kojouri: “We seek the fire of the spark that is already within us.” So, build and seek out your managed package spark.