Salesforce docs tends to write examples that use
global despite not needing to. From time to time, I've seen this on scheduled classes, batchable classes, queueable classes, etc. You should not generally follow this example. Basically, you should instead consider the purpose of the class at hand.
If it's in your own org, it should be
public, unless the compiler specifically tells you something must be
global. If it's in a managed package to be installed, it should be
public unless it is meant to be used directly by subscribers (the most usual case are utility classes for controlling behavior and scheduled classes that can be scheduled by the subscriber directly).
For all typical cases, you should assume that
public is the correct access modifier, unless the documentation specifically says "the access modifier must be global" (e.g. Considerations for Using the
webservice Keyword says "All classes that contain methods defined with the webservice keyword must be declared as global"), or it is a feature meant to be directly used by subscribers.
When in doubt, make your code
private. You can always promote it to
global later if you realize you made a mistake, but you can't go back down once you do go
global. Post-install handlers are one of those times where it typically doesn't make sense to have it be
global, because it may expose underlying data structures or secrets you don't want exposed unnecessarily.