Two Phoenix applications need to share data and communicate directly without the overhead of HTTP APIs, message queues, or shared databases, while managing node discovery in dynamic environments like Fly.io
Use Erlang's built-in RPC (Remote Procedure Call) to enable direct function calls between BEAM nodes: :rpc.call(node, Module, :function, [args], timeout). For GraphQL integration, reuse existing schemas through RPC instead of creating separate internal APIs: :rpc.call(remote_node, Absinthe, :run, [query, MyApp.Schema, [context: %{current_user_id: user_id}]], 30_000). This eliminates serialization overhead while maintaining authorization. For node discovery on platforms with dynamic naming, implement a custom libcluster strategy that queries EPMD directly: perform DNS lookup to get IPs, query EPMD on each IP for actual node names using :erl_epmd.names(ip), filter by basename prefix, and establish connections. This approach works best for same-language BEAM apps with shared codebases in trusted networks requiring rapid iteration, but creates implicit coupling without compile-time contract verification.