I am looking to confirm the best practice of storing client / secret credentials for multiple environments for multiple external webservices within salesforce.
Below is the analysis I have done using custom objects, custom settings, custom metadata types, and named credentials for this objective.
Custom Settings are controlled by Profile or by User.
Whereas Custom Objects are controlled with object and field level security and access is controlled by sharing settings.
I have seen some users use custom settings for credential storage, I'm assuming the reasons for this is by using the .get methods on the custom setting it will not count against your SOQL query limits and due it being stored in the application cache it is faster to access. In addition, you don't have to worry about users accessing / modifying the credentials unless they have the system permission to view and modify custom settings.
If I have various credentials to the various endpoints for the same service. Ex: dev.mycompany.com/data/, uat.mycompany.com/data/, prod.mycompany.com/data/ that are not specific to the user or profile, I find it excessive to add each environment, its subdomain, and its credentials (client secret) to a new field on the custom setting. In this example, if I would have 3 x 2 fields (client and secret) + 3 x 1 field (subdomain) + 1 field to determine which endpoint to hit depending on type of salesforce instance I'm on (dev, partial, prod).
Whereas with the custom object, I would have four fields (client, secret, active(boolean for whether or not this should the endpoint to request data from), and subdomain) and 3 records.
In addition, there is Custom Metadata types, which seem to be more or less like custom settings, but are stored as metadata as opposed to a table structure like custom settings / objects for simpler migration from environment to environment.
As for security I could encrypt the custom object fields as I can encrypt custom settings fields, however Salseforce seems to advise against the use of custom settings or custom metatypes to store credentials and recommends named credentials (which don't fit my use case of client/secret) or encrypted custom fields, due to custom metadata and custom settings being public.
I noted that other stack articles, such as: protected and public custom settings, suggest using protected custom settings to accomplish this, however I believe this answer was before custom metadata types existed.
Summary / Question:
Knowing this, based on my understanding of these three options, I believe it makes the most sense to store the credentials in a custom object from a security perspective and custom metadata / custom settings from a deployment perspective.
Given that security concerns would be my first priority, I'm leaning towards custom objects visible and editable only by system admins.
Is my understanding correct, is there other considerations that I have not made but need to weigh in making this decision?