We released global facing Invocable Apex Actions to be used by Process Builder, but would like to hide a couple of them from subscribing orgs.

From the official documentation on invocable methods, it doesn't look like this is possible:

Managed Packages: You can use invocable methods in packages, but once you add an invocable method you can’t remove it from later versions of the package.

Two questions:

  1. What's the best way to "hide" or mark this action as deprecated?

  2. Will 2nd generation packages (2GP) allow for removing of these classes/actions (if not now, in the future)?

1 Answer 1


This contains an opinion based on experience:

NEVER EVER EVER mark any code in a managed package as @Deprecated without first completely emptying its implementation.

Marking code as @Deprecated and including that in a release makes two things happen:

  1. The deprecated item is not visible on any new installs (though is visible to subscriber orgs that started with a version before the deprecation)
  2. The body of the deprecated item can never be changed!!!

If you leave the body in (we fell for this one - when something is deprecated you usually allow it to continue to work for people for a release or two but...) you make it such that any of the classes/methods/object types/fields/etc. that the deprecated code uses cannot be removed or changed. Ever. Because you can't change the deprecated body content. Ever.

This is a completely broken and very dangerous feature. We have code we can't refactor or remove because it is referenced by something we deprecated years ago. Never again.

So, from my perspective:

  1. Empty the method (make it just throw an exception with the message "Deprecated")
  2. Update whatever documentation you have to state that it is no longer valid to use it
  3. Quietly ignore it - it's up to you to decide whether to keep it in version control and on the release org, or just on your release org...

2GPs will eventually (or so I understand) allow you to delete pretty much whatever you like. However, in the meantime you can move the "dead" code into a separate sfdx source structure folder, such as force-app/main/defunct/classes, to declutter your main folder full of your maintained code.

However it is worth noting that it is not currently possible to migrate a 1GP managed package to 2GP and that this migration, as and when it arrives, is not likely to allow you to move the entire content of your 1GP to a 2GP and keep the same namespace. At least that's what I got from a call with a Salesforce Technical Evangelist 2 days ago. Note that 2GP migration will support keeping the namespace, despite previous advice.

  • 2
    I found this question (and answer) by accident and can confirm that the deprecation feature is very broken. It's additionally problematic if you're working with your packaging org and other orgs (e.g. for testing) - because you cannot use this annotation outside of a managed package! So all of a sudden at least one of your orgs is out of sync with your versioning. Managed packages are already broken in many ways - but this is the most dangerous feature I've come across.
    – Semmel
    Commented Aug 1, 2023 at 16:23

You must log in to answer this question.

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