How should I validate field values against an external service? I am looking at how to update a module that validates field values against an external service. Currently, it uses hook_form_alter().

I assumed I should:


Write a service that handles external communications and returns a Boolean value
Write a Constraint and a ConstraintValidator class that uses the service
Attach the ConstraintValidator object in hook_form_alter()


I assumed I would find a similar implementations in the code of the ReCaptcha or ReCaptcha V3 module. Neither of them uses that approach. I found the Field Validator module that is using constraints.

Is using a constraint validator the correct way, or are there other approaches?
As you want the field value to be validated, I would use a constraint, This ensures that the value is validated regardless of how the field value is saved - whether through a Form, an API (REST/JSON etc) or programatically.

As you didn't create the entities and fields yourself (I'm assuming you mean they're provided by a module or core, and not just that a former developer created them), you'll have to attach your constraint in hook_entity_bundle_field_info_alter() as explained in this post: How do I add a custom validation handler to an existing form/field?

Note however that this will mean anytime your entity has saved, and this field value has changed, your remote API will be called. If this is going to happen regularly, you may want to create some kind of caching system that caches the responses from the remote API.