So now you have in practice is a distributed monolith, with brittle, ad-hoc dependencies between services. A symptom is that most features require touching many MS.
If you build a car and send each team off to find the best parts in isolation and screw them together, you don't have the best car, you likely have something that doesn't even drive, because the parts don't fit. The performance of a system is in the interaction of its parts, not the sum of the performance of its parts taken individually.
Teams can never operate independently because it only ever makes sense to improve a part if it improves the functioning of the entire system. The whole problem with the microservices approach it that it optimizes the wrong thing.
It's absolutely necessary for very large organizations though. The alternative of trying to centrally plan the IT operations of an organization of, say, 500,000, gets to be quickly intractable.
Groups try to do it with frameworks like SAFe and while that may help a little bit, in the end you need to treat different parts of the organization as individual silos that are able to control and execute on their specific mission set within the wider org. Otherwise the complexity of the problem set they're dealing with makes it impossible to do anything without breaking other systems or teams.
It's much easier to start with a monolith and refactor it into microservices later than it is to refactor microservices written in different languages by different teams into a single codebase.
You could, of course, create this as a service. And then make possibly hundreds of calls to this service to generate a single web page.
Or, you can provide a library that does this, and the calls are cheap, reliable, and predictable.
Of course, if it is a service, the caller would locally the cache the information needed to make all the calls, do a batch call to the service, and then backfill in all the links. This then precludes generating and sending the page as you go, and creates the possibility for an explosion in complexity if a simple change in requirements that causes the arguments for the URL generation to be dependent on another service/library call.
Not everything should be a service call.
The schema and generated classes could be a shared common library that different teams can work on (maybe with some architecture obersight)
Or if using schema-less each library “knows” it’s own json formats
Then you get nice things like atomic transactions across multiple “services”. You also have no network concerns.
You can pull out microservices for things that need special attention. Such as a spikey-load service that might need to run as a lambda.
Version management is a solved problem. Use your languages package manager and semantic versions.
I concede you need to stick to one language. Ish. You have C FFIs. A .NET app could reference a dll written in C++ or Rust. But yeah not as flexible as services. Although there are inbetween things like RPC.
I agree to split into services where “you’r have to do that anyway”.
But adding services where part A of the monolith needs to use part B where a library would do the job seems odd.
If you are trying to solve a specific scaling issue, then sure, but this is rare.