Unfortunately there is no clean answer for this predicament, particularly when you are talking about UI code that is separate from the server code. It is very common to require those checks on both sides for the purpose of ensuring security.
Why do the checks in the UI?
- Helps provide feedback immediately to ensure the request is correct before it is ever sent
- Minimizes network traffic from well behaved clients
Why do the checks in the API?
- Not all clients are well behaved
- Protects against bad people who attempt to abuse your API to do what the UI won't allow
When things get messy
Most of the time, those double-checks are OK and reasonably justifiable. Unfortunately, it is pretty easy to get into a place where one API call can generate 30-70 calls in a microservice infrastructure. Typically it happens when you are not paying attention to how one service calls another, which in turn calls another. Logs are very useful to follow what is happening on any given request.
In situations like that, sometimes it is useful to have a layer handle the requests on your behalf and perform some intelligent caching. For example GraphQL will reduce the requests to microservices to just what is necessary to get your information.
Getting out of a mess requires:
- Understanding where the extra calls are coming from
- Understanding what in your architecture is encouraging duplicate calls
- Removing naive calls to get data you don't need
- Changing the design of your API or implementation that is causing the chain of requests
Nothing is a silver bullet (including GraphQL or caching). Unnecessary service calls happen because your services are requesting data they may have already received. Many times it is to support data calls that the user isn't even interested right now. The answer to my project most likely won't be the answer to your project.