Prerequisites
Umbrella Apps and Monorepo Architecture
Structure large Elixir systems with umbrella apps and monorepo boundaries. Covers app decomposition, dependencies, shared code, and team-scale workflows.
Umbrella projects are useful when a system grows beyond a single application but still benefits from coordinated development in one repository.
When Umbrella Makes Sense
Use umbrellas when:
- multiple deployable components share domain code,
- teams need clear ownership boundaries,
- coordinated refactors are frequent.
Avoid umbrellas when:
- services are fully independent and versioned separately,
- deployment cadence differs heavily between components.
Typical Layout
apps/
core_domain/
billing/
web/
worker/
Each app has its own mix.exs, dependencies, and OTP application config.
Dependency Rules
Strong pattern:
- domain apps depend only on stable lower-level libraries,
- web/worker apps depend on domain apps,
- never create circular dependencies.
Document these rules early and enforce in code review.
Shared Code Strategy
If code is reused by 2+ apps, extract it into a dedicated internal app with explicit API boundaries. Avoid ad-hoc imports from random sibling apps.
Build and CI Considerations
- run tests per app and for integration paths,
- cache dependencies at umbrella level,
- support targeted CI for changed apps where possible.
# Monorepo with multiple packages/services
# Similar trade-offs: shared tooling vs independent release cadence.
// Monorepo with workspaces/turborepo
// Shared packages + service apps in one repository.
# Umbrella
# Native Mix support for multi-app codebases with shared tooling.
Exercise
Split a Single App into an Umbrella
Take an existing app and split it into two apps:
- Extract core business logic into
core_domain. - Keep web adapters in
web. - Move shared contracts/types into explicit modules.
- Add tests that validate cross-app integration.
- Document dependency direction rules in the repo.
FAQ and Troubleshooting
Why does app startup fail after splitting?
Check application dependencies and startup order (extra_applications, supervision trees, and runtime config).
How small should each app be?
Split by ownership and change boundaries, not by arbitrary size.
Should every large Elixir repo become umbrella?
No. Umbrellas solve specific coordination and boundary problems; they add structure and overhead.
Related Lessons
Key Takeaways
- Umbrella apps help enforce boundaries in growing Elixir systems
- Dependency direction and ownership rules matter more than folder layout
- Shared code should be explicit libraries, not accidental cross-app coupling