I shipped a packaged integration that called an external service. API key in a named string, stored in a custom setting, encrypted in transit. It felt reasonable. The review did not agree. They cited a class of risk bigger than the one instance: any subscriber admin could read that setting, any support session could expose it, any log could leak it. They were right. I knew they were right.
My first instinct was to patch. Wrap the key more tightly. Rotate it on install, store it somewhere less readable. Classic instance-level thinking. A few days later I realized that was entirely the wrong frame.
Named Credentials and External Credentials exist to remove the authentication code from the app completely. The credential lives in the org's secure store. The app holds a reference, not a secret. When the callout fires, the platform resolves the credential, signs the request, and nothing sensitive ever passes through your Apex. The review finding moves from "you stored a secret" to "you hold no secret." Those are completely different conversations.
Protected Custom Metadata solves the adjacent case: configuration values that need to travel with the package but must not be readable by subscriber admins. The protection is declared in the metadata type itself. No application code needs to enforce it. The platform does. That is the whole design.
The third piece hit harder. I had seen UserInfo.getSessionId() passed to external systems as a token. It reads like it should work, and in an unpackaged org it sometimes does, for a while. In a packaged context it is a compliance risk with a timer on it. Session IDs were never meant to leave the trust boundary of the org. Named Credentials make the whole pattern unnecessary.
What shifted was the category. Before, I was patching secrets. After, I was removing the conditions under which secrets could exist. The packaged app no longer had an auth layer to audit because the platform held it. That felt like a different kind of win.
If you are building for AppExchange, the review will find it. The question is whether you find it first, and whether your response is a patch or a pattern change. The pattern change costs more once. Then that class of problem is gone.