Question

I'm trying to learn about microservices and best practices and came across this scenario and didn't know what was the correct way of approaching it:

I have a website that can display widgets (let's say there's 3 types of widgets, widget A, B, and C) specified by a user. Each widget type has a corresponding microservice (Service A, B, and C) that serves data for each widget type, respectively. The user can save the widgets they want to display into a profile - I'm assuming logically, there's a User Profile Service that stores all the profiles.

One of the designs that makes sense for this is Backends for Frontends method where the website would call an backend service that aggregates all the data to show the user from Services A, B, and C. My question is, who and what is responsible for getting the user profile so the backend service knows what to query for in Services A, B, and C?

If the backend queries the User Profile Service and then queries Services A, B, and C based on the response of the User Profile Service, doesn't that introduce a synchronous communication which is frowned upon?

If the website first queries the User Profile Service and then queries the backend service, doesn't that introduce more chatter between the client and the server?

What's the "correct" way of getting a user profile and aggregating data from difference services based on the profile? Or am I thinking about this incorrectly?

Was it helpful?

Solution

One really important thing to consider is "Decoupling". Not going much into what they mean, decoupling is when a life cycle of service is not very dependent on other services.

Coming to your use case, If the client interacts with a lot of services directly, you are creating a coupling between the client and the services, which is undesirable. Your client now has to be aware of all services it interacts with and has a risk of inducing regression.

This is where Backend For Fronted (BFF) layer comes in. BFF acts as a layer of abstraction and the client needs to be aware of only what interfaces are available here. BFF, which although sits between client and backend, is a service you have greater control over, in terms of changes or deployments made.

You might be wondering what's done here is we moved the coupling between client and 3 services to Aggregator and 3 services. The number of dependencies will remain the same (unless you merge a few services to one, as part of better design or worse - Monolith), it's about how you handle the dependencies. The client is a third party, and you do not enforce the responsibility of maintenance on the client.

And so you move that responsibility to the aggregator which you have greater control over, making it

a) Easier for the client to integrate.

b) Easier for you to maintain due to less nonmanageable dependencies.

c) Create separation between internal and external services.

If the backend queries the User Profile Service and then queries Services A, B, and C based on the response of the User Profile Service, doesn't that introduce a synchronous communication which is frowned upon?

-- Just because User Profile depends on A, B and C doesn't mean the communication has to be synchronous. If A, B and C are decomposed properly, you can gain a lot by making parallel/async calls to them. This depends on the design, it is sometimes worth relooking at whether you overdid your decomposition.

I think you were thinking along the right lines by having a BFF the client interacts with and BFF being more aware of other services.

Licensed under: CC-BY-SA with attribution
scroll top