{"id":37350896,"url":"https://github.com/eigr/mesh","last_synced_at":"2026-01-16T04:02:24.027Z","repository":{"id":331554037,"uuid":"1130671639","full_name":"eigr/mesh","owner":"eigr","description":"Capability-based distributed service discovery and process lifecycle management","archived":false,"fork":false,"pushed_at":"2026-01-10T12:21:31.000Z","size":744,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-11T00:41:33.739Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eigr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-08T20:56:40.000Z","updated_at":"2026-01-10T21:27:11.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/eigr/mesh","commit_stats":null,"previous_names":["eigr/mesh"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/eigr/mesh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eigr%2Fmesh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eigr%2Fmesh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eigr%2Fmesh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eigr%2Fmesh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eigr","download_url":"https://codeload.github.com/eigr/mesh/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eigr%2Fmesh/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28477206,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T03:13:13.607Z","status":"ssl_error","status_checked_at":"2026-01-16T03:11:47.863Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-16T04:02:23.338Z","updated_at":"2026-01-16T04:02:24.016Z","avatar_url":"https://github.com/eigr.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mesh\n\nCapability-based distributed process management for Elixir.\n\nMesh distributes GenServer processes across BEAM nodes using shard-based routing and capabilities. Processes are lazily activated on-demand and automatically placed on the correct node based on their ID and capability type.\n\n## What is Mesh?\n\nMesh solves the distributed process placement problem. Instead of manually managing where processes run, you define capabilities (like `:game`, `:chat`, `:payment`) and let Mesh handle the routing using shards distributed across your cluster.\n\nKey characteristics:\n\n- Deterministic placement: Same ID always routes to same node\n- Lazy activation: Processes created on first invocation\n- Zero coordination: No distributed locks or consensus\n- High throughput: 16,000+ process creations/s, 30,000+ requests/s\n- Library design: You control your supervision tree\n\nUse cases: game servers with regional routing, multi-tenant systems with workload isolation, microservice patterns where different node types handle different request types.\n\n## Core Concepts\n\n### Capabilities\n\nCapabilities are labels that define what types of processes a node can handle. Think of them as tags that describe a node's responsibility in your cluster.\n\nFor example:\n- `:game` - This node handles game-related processes\n- `:chat` - This node handles chat/messaging processes  \n- `:payment` - This node handles payment processing\n\nNodes register the capabilities they support, and Mesh automatically routes process requests to nodes with matching capabilities. This enables workload isolation and specialized node types.\n\n```elixir\nMesh.register_capabilities([:game, :chat])\n```\n\nMesh uses shards to distribute processes across nodes:\n\n```\nprocess_id → shard → owner_node\n```\n\nSame ID always maps to the same shard. Shards are automatically distributed across nodes supporting the required capability. When cluster topology changes (nodes joining/leaving), shards are rebalanced accordingly.\n\n\u003e__NOTE__: The default shard strategy (`EventualConsistency`) uses **eventual consistency** for process placement. Shards are used purely for routing decisions - they do not provide state guarantees or transactions. Each process manages its own state independently. During network partitions, the same process ID may temporarily exist on multiple nodes until the system converges. When topology changes occur (nodes joining/leaving), rebalancing stops conflicting processes so they can be migrated to the correct node on their next invocation. You can implement custom shard strategies with different consistency guarantees - see [Configuration](docs/guides/getting_started/configuration.md).\n\nProcesses are created lazily on first invocation. When you call a non-existent process, Mesh:\n1. Determines target node via shard routing\n2. Starts the process on that node\n3. Caches the PID for fast subsequent lookups\n4. Forwards the message and returns the response\n\nThis eliminates manual lifecycle management.\n\n## Quick Start\n\nAdd to `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:mesh, \"~\u003e 0.1\"},\n    {:libcluster, \"~\u003e 3.3\"}\n  ]\nend\n```\n\nStart Mesh in your application:\n\n```elixir\ndefmodule MyApp.Application do\n  use Application\n\n  def start(_type, _args) do\n    topologies = [\n      gossip: [\n        strategy: Cluster.Strategy.Gossip,\n        config: [port: 45892, if_addr: \"0.0.0.0\"]\n      ]\n    ]\n\n    children = [\n      {Mesh.Supervisor, topologies: topologies}\n    ]\n\n    Supervisor.start_link(children, strategy: :one_for_one)\n  end\nend\n```\n\nDefine a GenServer:\n\n```elixir\ndefmodule MyApp.Counter do\n  use GenServer\n\n  def start_link(process_id) do\n    GenServer.start_link(__MODULE__, process_id)\n  end\n\n  def init(process_id) do\n    {:ok, %{id: process_id, count: 0}}\n  end\n\n  def handle_call({:actor_call, _payload}, _from, state) do\n    new_count = state.count + 1\n    {:reply, {:ok, new_count}, %{state | count: new_count}}\n  end\nend\n```\n\nRegister capabilities and invoke:\n\n```elixir\nMesh.register_capabilities([:counter])\n\n{:ok, pid, result} = Mesh.call(%Mesh.Request{\n  module: MyApp.Counter,\n  id: \"counter_1\",\n  payload: %{},\n  capability: :counter\n})\n```\n\n## API\n\n`Mesh.call/1` - Synchronous invocation\n\n```elixir\n{:ok, pid, response} = Mesh.call(%Mesh.Request{\n  module: MyApp.Counter,\n  id: \"counter_1\",\n  payload: %{action: :increment},\n  capability: :counter\n})\n```\n\n`Mesh.cast/1` - Fire-and-forget invocation\n\n```elixir\n:ok = Mesh.cast(%Mesh.Request{\n  module: MyApp.Counter,\n  id: \"counter_1\",\n  payload: %{action: :reset},\n  capability: :counter\n})\n```\n\n`Mesh.register_capabilities/1` - Register supported capabilities\n\n```elixir\nMesh.register_capabilities([:game, :chat, :payment])\n```\n\n## Cluster Setup\n\nSingle-node development:\n\n```elixir\niex -S mix\niex\u003e Mesh.register_capabilities([:game, :chat])\n```\n\nMulti-node with Gossip:\n\n```bash\n# Terminal 1\niex --sname game@localhost --cookie mesh -S mix\niex\u003e Mesh.register_capabilities([:game])\n\n# Terminal 2\niex --sname chat@localhost --cookie mesh -S mix\niex\u003e Mesh.register_capabilities([:chat])\n```\n\nKubernetes deployment:\n\n```elixir\nconfig :libcluster,\n  topologies: [\n    k8s: [\n      strategy: Cluster.Strategy.Kubernetes.DNS,\n      config: [\n        service: \"mesh-headless\",\n        application_name: \"mesh\"\n      ]\n    ]\n  ]\n```\n\n## Performance\n\nRun benchmarks:\n\n```bash\nmix run scripts/benchmark_singlenode.exs\nelixir --name bench@127.0.0.1 --cookie mesh -S mix run scripts/benchmark_multinode.exs\n```\n\n## Documentation\n\n- [Quickstart Guide](docs/guides/getting_started/quickstart.livemd) - Get started in 5 minutes\n- [Configuration](docs/guides/getting_started/configuration.md) - Configure shard strategies and distribution\n- [Clustering](docs/guides/getting_started/clustering.md) - Multi-node setup\n- [Sharding](docs/guides/advanced/sharding.md) - Process distribution internals\n- [Implementing Processes](docs/guides/advanced/processes.md) - Building stateful actors\n\n## Development\n\nUsing Make:\n\n```bash\nmake help          # Show all commands\nmake all           # Install, compile, test\nmake dev           # Start IEx session\nmake test          # Run tests\nmake benchmark     # Run single-node benchmark\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feigr%2Fmesh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feigr%2Fmesh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feigr%2Fmesh/lists"}