ExServiceMeshRouter
A BEAM-native service mesh gateway for Phoenix umbrella applications with automatic service discovery. Tenant handling is owned by each Phoenix application.
Architecture Overview
Request Flow
Client Request
→ Gateway Router
→ Service Registry (host → endpoint)
→ Phoenix Endpoint
→ Phoenix App Router
→ Tenant Plug (inside app)
→ Controllers / LiveView
Installation
If available in Hex, the package can be installed
by adding ex_service_mesh_router to your list of dependencies in mix.exs:
def deps do
[
{:ex_service_mesh_router, ">= 0.0.0"}
]
end
Configuration
config :ex_service_mesh_router,
port: 4000
Key Design Principles
1. Gateway is service-only
The gateway ONLY routes by host:
- auth.local → AuthWeb.Endpoint
- billing.local → BillingWeb.Endpoint
No tenant logic exists in the gateway.
2. Phoenix apps own tenants
Each Phoenix app is responsible for:
- tenant extraction
- tenant assignment
- tenant isolation
- data scoping
3. Shared tenant resolver
A shared module provides consistent tenant parsing across apps.
Project Structure
lib/ router/ application.ex router.ex registry.ex
shared/ tenant_resolver.ex
How It Works
1. Service discovery
At startup, the gateway scans loaded umbrella apps and builds a routing table from Phoenix endpoint config:
Example config:
config :auth_web, AuthWeb.Endpoint, url: [host: "auth.local", port: 4001]
Becomes:
auth.local → AuthWeb.Endpoint
2. Routing
Request:
Flow:
- Extract host header
- Lookup endpoint in registry
- Forward request to Phoenix endpoint
3. Tenant handling (inside Phoenix apps)
Example:
tenant1.auth.local
Inside Auth app:
- Tenant Plug extracts "tenant1"
- Assigns:
conn.assigns.tenant = "tenant1"
Shared Tenant Resolver
Used by all Phoenix apps:
Router.Shared.TenantResolver.resolve("tenant1.auth.local")
Configuration
Example Phoenix app config
config :auth_web, AuthWeb.Endpoint, url: [ host: "auth.local", port: 4001 ]
config :auth_web, endpoint: AuthWeb.Endpoint
Running the system
Install dependencies
mix deps.get mix compile
Start server
mix phx.server
Local DNS (development)
127.0.0.1 auth.local 127.0.0.1 billing.local
Test URLs
http://auth.local:4000
http://billing.local:4000
What this does NOT do
- SSL termination
- database routing
- authentication/authorization
- circuit breaking
- tenant provisioning
These belong in:
- Phoenix apps
- infrastructure layer
Mental model
A BEAM-native ingress router where:
- Gateway routes services
- Phoenix apps own tenants
- Each app is an isolated tenant runtime