Each microservice queries other microservices for data when it’s needed.
This is the instinctive choice for developers from a monolithic application background. The developer replaces local method calls with remote calls (e.g. REST).
Advantages:
Live data
The data you get back is the current state of the supplying microservice. However, you still have to deal with eventual-consistency and the lack of transaction isolation between microservices.
Either it works or it doesn’t
Failures are associated with a given request; this makes them easier to identify and resolve. Unfortunately, stack-traces are not passed between microservices. You have to setup distributed tracing to get easy access to the root cause (see OpenTracing).
There are no additional artifacts to release/deploy/run
The integration is contained within the existing microservices.
Code generation support
You can generally define your remote API specification (e.g. in OpenAPI specification) then code generate the model, server and client from it.
https://medium.com/@john_freeman/querying-data-across-microservices-8d7a4667668a