Question regarding GenServer use

I’ve been breaking an app up into smaller apps inside an umbrella project, (using ideas from Domain Driven Design diagram for Umbrella app - #11 by hlx and With Phoenix on a umbrella we lost the ability to join several functions together - #20 by benperiton) but breaking them up by feature, so a ‘Sales’ app’, ‘Accounting app’ etc and I now need to communicate between them.

There is a GraphQL interface that runs on Phoenix and Absinthe, and my original thought was to just call the modules directly, so I could call App.Feature.Sales.OrderService.place_order() for instance, but that then makes it quite tightly coupled.

So last night I was thinking I could perhaps use a GenServer in each ‘Feature app’ and then use that as the API that the resolvers use to communicate with the ‘feature apps’. In fact, the other ‘feature apps’ could also use this to communicate between themselves.

Something like:

Is this a good use of a GenServer, or is it the wrong way to approach this?

2 Likes

If you only want to decrease the surface, a simpler “API module” would be enough here.

A GenServer would not really help with decoupling, I think. What do you think would be the benefits when adding GenServers?

3 Likes

I would recommend looking at GenServer not as mechanism for design boundaries but rather as a mechanism for state and concurrency. If you put each of those features behind a GenServer, there is a high chance you are introducing bottlenecks in your system. The design boundaries in Elixir are modules and functions, not processes.

5 Likes

My thinking behind using a GenServer was that there will be some features that will have functions being hit hundreds or thousands of times a minute, so I thought that it might help with that? (One will be used to process inbound call records as they happen, pulling from RabbitMQ)

There will also be ‘fire-and-forget’ calls that will just trigger backend jobs, as well as timed calls (I think I can use send_after for this?)

So would it be better to just have an API Module for each app, then have a GenServer purely for the apps that need to have ‘fire-and-forget’ and timed things?

1 Like