We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
Umbrella Applications at Scale: Managing 94 Apps
Lessons from running one of the largest Elixir umbrella projects
Prismatic Engineering
Prismatic Platform
Why Umbrella?
The Prismatic Platform started as a single Phoenix application. As features grew
-- OSINT tools, due diligence pipelines, authentication, storage adapters,
telemetry, compliance engines -- the codebase became difficult to navigate and
test. Converting to an umbrella project provided clear domain boundaries while
keeping everything in a single repository.
Today the platform runs 94 applications in one umbrella, spanning domains
from cryptographic storage to AI agent orchestration.
Domain Boundary Design
Each umbrella app owns a specific domain. The naming convention signals the
domain clearly:
|--------|--------|-------------|
prismatic_storage_*prismatic_storage_ecto, prismatic_storage_etsprismatic_osint_*prismatic_osint_core, prismatic_osint_sourcesprismatic_*_webprismatic_web, prismatic_perimeter_webprismatic_dd*prismatic_dd, prismatic_dd_dataroomThe key rule: apps depend downward, never upward. Storage apps never depend
on web apps. Core business logic never depends on presentation. This is enforced
by the dependency graph in each app's mix.exs.
Dependency Management
With 94 apps, dependency conflicts are a real risk. The platform uses several
strategies:
Shared dependencies in root mix.exs: Common dependencies like jason,
telemetry, and plug are declared in the root project to ensure version
consistency.
Explicit inter-app dependencies: Each app declares exactly which sibling
apps it depends on. This makes the dependency graph explicit and auditable:
# apps/prismatic_dd/mix.exs
defp deps do
[
{:prismatic, in_umbrella: true},
{:prismatic_storage_core, in_umbrella: true},
{:prismatic_osint_core, in_umbrella: true}
]
end
The DEPS doctrine: Version constraints are mandatory. No ~> 0.0 or git
dependencies pointing to unstable branches. Override dependencies require
written justification in comments.
Cross-App Communication
Apps communicate through three mechanisms:
1. Direct Function Calls
When app A depends on app B, it calls B's public API directly. This is the
simplest and most common pattern:
# From prismatic_dd, calling prismatic_osint_core
PrismaticOsintCore.search(:czech_ares, %{ico: "12345678"})
2. Phoenix PubSub
For decoupled, event-driven communication, apps publish and subscribe to topics
without direct dependencies:
# Publisher (prismatic_dd)
Phoenix.PubSub.broadcast(Prismatic.PubSub, "dd:pipeline", {:entity_loaded, entity})
# Subscriber (prismatic_web) - no dependency on prismatic_dd
Phoenix.PubSub.subscribe(Prismatic.PubSub, "dd:pipeline")
3. Storage Traits
The prismatic_storage_core app defines behaviour callbacks that storage
adapters implement. Any app can use storage without knowing which adapter
is active:
PrismaticStorageCore.store(:default, key, value)
PrismaticStorageCore.fetch(:default, key)
Compilation and Testing at Scale
Compiling 94 apps takes time. The platform uses several optimizations:
mix compile compiles independent apps in parallelmix test apps/prismatic_dd runs only one app's testsThe full test suite (6,330 test files) takes several minutes to run. CI runs the
full suite; local development uses targeted testing.
Challenges and Solutions
Challenge: Circular Dependencies
Two apps that depend on each other create a compilation deadlock. The solution is
to extract the shared interface into a third app. The platform has several
-core apps (prismatic_osint_core, prismatic_storage_core) that exist
solely to break cycles.
Challenge: Configuration Sprawl
With 94 apps, config/config.exs could become enormous. Each app owns its own
configuration namespace, and the root config only sets cross-cutting concerns
like logger level and PubSub configuration.
Challenge: Knowing Where Code Lives
New developers struggle to find code in 94 apps. The platform addresses this with
the RDME doctrine (every app has a README), the Knowledge Index (21,000+ document
cross-reference), and the /agents command that routes questions to the right
domain expert.
Is Umbrella Right for You?
Umbrella projects shine when you have clear domain boundaries, a single team
(or tightly coordinated teams), and shared infrastructure. They struggle when
apps need independent deployment schedules or when teams cannot coordinate
releases. For the Prismatic Platform, the umbrella structure has been a net
positive, enabling code reuse and consistent quality enforcement across all
94 applications.