How to make right usage of umbrella apps?

Hello, i’m building a new app in elixir to show what elixir can do inside my company, this app is basically a internal administration panel that makes requests to very different apps and produces data to the front end, and have its own small database for a few state management.
Regarding the project structure, i was thinking on creating it with umbrella projects in the following way:

└── apps
    ├── api           <- my api, wich would gather information from all the other apps
    ├── usecases <- my business rules
    ├── repository <- my only point of interaction with the database
    ├── service_a  <- external service i need to call
    └── service_b  <- another external service i need to call

Basically, api will call usecases, but never the other apps, and usecase will call the services and repository.

Is this a right approach to make an elixir app with umbrella? Is it wasteful?

My main goal with this project is show that elixir can be a viable solution for some of the problems we have, therefore i want to start with a small project but i want to get it right.

3 Likes

Hi @prabello,

It’s great to see you trying to convince your company to use Elixir, but it would also be good, if you can give us some points regarding what kind of issues, you’re trying to tackle…

Thanks.

Umbrella app allow you to declare explicit dependency between individual app. However, if it’s to show how an Elixir app can organize things… probably you can start with single non-umbrella app using module to separate “domains”. Just because “umbrella app” is another thing to learn…

Module structure will be like this:

  • In umbrella: MyAppUmbrella.Api, MyAppUmbrella.ServiceA
  • In non-umbrella: MyApp.Api, MyApp.ServiceA.

It’s pretty straightfoward to convert an app with well-defined module to umbrella (or vice versa) - so you’re not locked in the initial decision. Don’t worry!

2 Likes

My first approach is to basically show that elixir can be as productive as any other language to develop REST APIs (witch is the most part of ours apps) and can be maintained.

My idea is to start with a basic app that does a lot of http calls and serve these requests back (usually we do these in nodejs)

And if it goes well evolve into more critical and complex system, such as part of ours internal services

I see, makes a lot of sense.

My main point is if this kind of division makes sense in elixir or is there any other preferable approach?

My thoughts are, since this is a embryonic project, not using umbrella may make the libs end up messing responsibilities and then it could be seen as a failure, thats why starting with a more complex, yet, safer approach (or at least thats what i felt)

Umbrella forces you think about responsibility, so I prefer umbrella app. Also you can test them independently (mix test in apps/service_a)

If you can set up all things (division of apps, set up all umbrella stuff like test coverage etc) then setting up an umbrella app and invite others to contribute to individual apps would be nice. I’ve done that, and it was smooth, even all were relative new to elixir.

If you need to do more experiment on how to divide apps, etc. - it may be better to start as non-umbrella app. As I said, it’s pretty simple to migrate to umbrella app later :smile:

1 Like

Hi @prabello,

Welcome to BEAM world! As you have mentioned lots of http calls are going to be used, your choice of language is great! I’m not going to debate about other potential choices, but anything is achievable in elixir except certain instances like numeric computations that involves a huge processing might not work.

First thing, when people adopt functional programming, they feel difficult is the conventions which are bizarre in the beginning and once they get a grasp, they can easily understand the implementaions.

Please read this from the official site:
https://elixir-lang.org/getting-started/mix-otp/dependencies-and-umbrella-projects.html#dont-drink-the-kool-aid

That is what gave me the idea of splitting a huge domain application into multiple smaller modules, which can be shared with remote teams without affecting the other deliverables.

Since, this is an early stage for you, I’d recommend to keep things as simple as possible and once, you’re ready to deep dive, you can look at potential toolchains for helping you in easing the deployment and other stuffs.

Thanks.

Hi @prabello,

I view umbrellas more as a mono-repo project. It allows me to decide if I want to run everything inside a single node (like on my machine for development), or to bundle apps together for a release (OTP release, docker image…). For example, you could have an OTP app that does some tracing or telemetry that you package with each service you release in order to have a consistent way to monitor your system in production.

I don’t think your approach is wasteful, but you could essentially start with an umbrella with a single OTP app in it, and extract modules into their own apps gradually as you learn about your domain, architecture & boundaries.

At least that’s how I personally see it, I would love to learn how everybody else does it though!

1 Like

That’s how exactly how I use umbrellas even in my hobby projects. Umbrellas are simply more future-proof in my eyes.

Also, you completely nailed it right here. Mono-repos have a lot of undeniable benefits over internal but still fragmented dependencies.

1 Like

I aggree. The only hurdle (probably because I don’t do it often enough), is your CI config. Knowing what apps to release according to the changes. Especially if there’s an umbrella dependency. Example: a tracing wrapper around telemetry & datadog, being used by multiple components of the umbrella. When I upgrade my monitoring library, I may need to release a ton of new versions of these components.