Project structure - Umbrella or Poncho approaches?

Hi everyone!
I’ve been in Elixir for 3 months and I want to develop a platform which has to support a lot of concurrent users (+50.000, by the moment). I’ve learned a lot about the language and some advises that the community shares constantly. But my main question appears when I think about the project structure. This platform will have a lot of modules, maybe about 10 (and not little ones, so perhaps I should split some of them), and some of them should use Phoenix (but not all of them).
I’ve searched about Umbrella structure and I think that I know more or less how it works. But also I’ve found that a lot of people does not recommend it when talking about production. Then I searched a little bit more and I found articles about the Poncho mindset, which isolates completely and works using the paths / repositories dependencies.
I’ve seen some topics talking about this, but they don’t really have a solid conclusion (there are still some Umbrella followers).
So my question would be: what is the best project structure when we talk about a platform of this size (thinking in future scalability), and if a Poncho structure would make it slower or faster?

Thanks a lot!!

4 Likes

I feel like arguing about plain mix projects and poncho or umbrella style projects is the wrong level.

In elixir you basically have two kinds of “structure”. Structure of code – which should be handled by modules and folders in your source code – and structure of runtime concerns, like dependencies or being able to run parts of your application independently from others – which is what drives how you set up supervision trees or multiple otp applications.

What’s often criticized with umbrellas is using the latter solution (otp applications) for the first reasoning. Don’t just put code in multiple otp applications if those parts of code are not meant to be run in isolation. A single otp application is just fine for that.

On the other hand if you intend to split up your application at runtime e.g. over multiple nodes then go for properly devided otp applications.

As for poncho vs. umbrella. Poncho style project setups are way more explicit especially when it comes to configuration. With umbrellas people often seem to have problems with the fact that config (just like dependencies) are set for the whole umbrella. With elixir 1.9 this is even enforced by the generators, which no longer generate application level config in umbrellas. For the nerves people where configuration is even more complex because of target machine differences the solution was to just not use umbrellas. Personally I feel like both are usable and you need to find what style of thinking about/working with your application suits you more. Either “one piece at a time” (poncho) or “the whole as the sum of all parts” (umbrella).

10 Likes

Yeah! I will have more than one server running different elixir services.

Since you say that Elixir 1.9 does not generate application level config in umbrellas, maybe it’s better to implement a Poncho in my case. New people in the project and people that is not familiarized with Elixir will appreciate it!

Thanks a lot again, see you in other posts!

Just to be sure: Application config at runtime is always global to all the applications running in a given beam instance. This is true for ponchos as well as umbrellas. The difference is just that in an umbrella you have one set of config files for all applications (even if you just run a single one), while in ponchos you have a set of configs per otp application and it’ll use the ones of the application folder you’re currently in, while ignoring any config of dependencies (even if they’re part of the poncho). Ponchos make it easier to develop thing independently from each other, while umbrellas will slap you on your fingers earlier if you try to introduce incompatibilities between multiple applications (e.g. contradicting config for common dependencies).

So maybe an Umbrella is easier to maintain, because you don’t have to update separately every component. But…

maybe if you are working in a big project and you have incompatibilities, it’s better to adopt Poncho.

If that’s the main difference, then as a solution we could set separately also the dependency in every mix file, isn’t it?

IMHO there is almost no difference between these two approaches since 1.9 (and earlier the only difference in reality was handling the configuration). Right now I would go with Umbrellas even more, as it provides what I want almost directly OOTB and with Poncho I need to manage everything by myself or use external tools.

3 Likes

If you have incompatibilities you’ll have them with the poncho style project as well. At runtime things are run exactly the same. In umbrellas you’re just forced to spot those issues as you’ll always maintain just one set of configs / run apps together more often, while for poncho applications those things might be discovered later e.g. when switching to a “higher level” application. Both have their place though and it’s a tradeoff between more flexibility and tighter control.

Personally I feel like poncho style applications make the most sense in loosely coupled projects like nerves. There might be an application for talking to a special sensor and it just needs to be included to be called from elsewhere, but there are no other dependencies between applications. If things are more coupled, but e.g. in separate apps to split load or failures predictable between different nodes I’d rather opt for an umbrella.

3 Likes