{"id":33902481,"url":"https://github.com/elixir-horde/horde","last_synced_at":"2026-07-02T13:01:48.480Z","repository":{"id":37730671,"uuid":"132625346","full_name":"elixir-horde/horde","owner":"elixir-horde","description":"Horde is a distributed Supervisor and Registry backed by Postgres","archived":false,"fork":false,"pushed_at":"2026-03-13T21:30:49.000Z","size":879,"stargazers_count":1464,"open_issues_count":2,"forks_count":118,"subscribers_count":24,"default_branch":"master","last_synced_at":"2026-03-14T08:25:27.270Z","etag":null,"topics":["cluster","elixir","registry","supervisor"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elixir-horde.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"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":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-05-08T15:01:01.000Z","updated_at":"2026-03-13T21:30:53.000Z","dependencies_parsed_at":"2023-01-27T13:31:21.866Z","dependency_job_id":"5c9d7645-5991-4f2c-b7f3-23e63e5e136c","html_url":"https://github.com/elixir-horde/horde","commit_stats":{"total_commits":496,"total_committers":51,"mean_commits":9.72549019607843,"dds":0.2681451612903226,"last_synced_commit":"dbe0f6d8e8c39a53da6f7332c9e90659aee49a47"},"previous_names":["elixir-horde/horde","derekkraan/horde"],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/elixir-horde/horde","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-horde%2Fhorde","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-horde%2Fhorde/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-horde%2Fhorde/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-horde%2Fhorde/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elixir-horde","download_url":"https://codeload.github.com/elixir-horde/horde/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-horde%2Fhorde/sbom","scorecard":{"id":335265,"data":{"date":"2025-08-11","repo":{"name":"github.com/derekkraan/horde","commit":"54d03144af6c9f7aeec47e9bf7fd32958c1add8a"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.6,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":3,"reason":"Found 8/24 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":3,"reason":"4 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/derekkraan/horde/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/derekkraan/horde/ci.yml/master?enable=pin","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":10,"reason":"project is fuzzed","details":["Info: ElixirPropertyBasedTesting integration found: test/uniform_distribution_test.exs:3","Info: ElixirPropertyBasedTesting integration found: test/uniform_quorum_distribution_test.exs:3","Info: ElixirPropertyBasedTesting integration found: test/uniform_random_distribution_test.exs:3"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 15 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T04:35:17.998Z","repository_id":37730671,"created_at":"2025-08-18T04:35:17.998Z","updated_at":"2025-08-18T04:35:17.998Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35048062,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-02T02:00:06.368Z","response_time":173,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["cluster","elixir","registry","supervisor"],"created_at":"2025-12-12T00:30:41.920Z","updated_at":"2026-07-02T13:01:48.459Z","avatar_url":"https://github.com/elixir-horde.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Horde [![Hex pm](http://img.shields.io/hexpm/v/horde.svg?style=flat)](https://hex.pm/packages/horde) [![.github/workflows/ci.yml](https://github.com/derekkraan/horde/actions/workflows/ci.yml/badge.svg)](https://github.com/derekkraan/horde/actions/workflows/ci.yml) [![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/horde)\n\n\nDistribute your application over multiple servers with Horde.\n\nHorde is comprised of `Horde.DynamicSupervisor`, a distributed supervisor, and `Horde.Registry`, a distributed registry. Horde is built on top of [DeltaCrdt](https://github.com/derekkraan/delta_crdt_ex).\n\nRead the [full documentation](https://hexdocs.pm/horde) on hexdocs.pm.\n\nThere is an [introductory blog post](https://moosecode.nl/blog/introducing_horde) and a [getting started guide](https://moosecode.nl/blog/getting_started_horde). You can also find me in the Elixir slack channel #horde.\n\nDaniel Azuma gave [a great talk](https://www.youtube.com/watch?v=nLApFANtkHs) at ElixirConf US 2018 where he demonstrated Horde's Supervisor and Registry.\n\nSince Horde is built on CRDTs, it is eventually (as opposed to immediately) consistent, although it does sync its state with its neighbours rather aggressively. Cluster membership in Horde is fully dynamic; nodes can be added and removed at any time and Horde will continue to operate as expected. `Horde.DynamicSupervisor` also uses a hash ring to limit any possible race conditions to times when cluster membership is changing. \n\n`Horde.Registry` and `Horde.DynamicSupervisor` are both designed to stay as close as possible to the API and behavior of their counterparts in Elixir’s standard library. For most scenarios, they can be used as drop-in replacements with minimal changes required.\n\nSome differences do exist — such as the current lack of support for keys: :duplicate in Horde.Registry — but these divergences occur only when standard library behavior does not translate well to a system that is inherently distributed.\n\nOur goal is to keep these differences to the absolute minimum necessary, while ensuring that Horde remains reliable, consistent, and optimized for distributed environments. See [documentation of Horde.DynamicSupervisor.start_link/1](https://hexdocs.pm/horde/Horde.DynamicSupervisor.html#start_link/1) for details.\n\n## Running a single global process\n\nIf you simply need to run a single process as a singleton in your cluster, I would encourage you to look at [Highlander](https://github.com/derekkraan/highlander) or [HighlanderPG](https://hex.codecodeship.com/package/highlander_pg) instead, as one of these may fit your use case better.\n\n## 1.0 release\n\nHelp us get to 1.0, please fill out our [very short survey](https://docs.google.com/forms/d/e/1FAIpQLSd0fGMuELJIKAiaR1XlvHKjpSo024cojktXjp4ASM7MSXTYfg/viewform?usp=sf_link) and report any issues you encounter when using Horde.\n\n## Fault tolerance\n\nIf a node fails (or otherwise becomes unreachable) then Horde.DynamicSupervisor will redistribute processes among the remaining nodes.\n\nYou can choose what to do in the event of a network partition by specifying `:distribution_strategy` in the options for `Horde.DynamicSupervisor.start_link/2`. Setting this option to `Horde.UniformDistribution` (which is the default) distributes processes using a hash mechanism among all reachable nodes. In the event of a network partition, both sides of the partition will continue to operate. Setting it to `Horde.UniformQuorumDistribution` will operate in the same way, but will shut down if less than half of the cluster is reachable.\n\n## CAP Theorem\n\nHorde is eventually consistent, which means that Horde can guarantee availability and partition tolerancy. Horde cannot guarantee consistency. This means you may end up with duplicate processes in your cluster. Horde does aggressively synchronize between nodes (this is also tunable), but ultimately, depending on the tuning parameters you choose and the quality of the network, there are conditions under which it is possible to have duplicate processes in your cluster. Horde.Registry terminates duplicate processes as soon as they are discovered with a special exit code, so you'll always know when this is happening. See [this page in the docs](https://hexdocs.pm/horde/eventual_consistency.html#horde-registry-merge-conflict) for more details.\n\n_NOTE: Since Horde 0.6.0, Horde.DynamicSupervisor ignores the `id` of a child spec (as Elixir.DynamicSupervisor does), and therefore does not guarantee that each `id` will be unique in the cluster (as it did pre-0.6.0). If you want to uniquely name your processes in a cluster, use Horde.Registry for this purpose. Having both Horde.DynamicSupervisor and Horde.Registry checking for uniqueness was subject to a race condition where Horde.DynamicSupervisor would choose process A to survive and Horde.Registry would choose process B to survive, resulting in both processes being killed._\n\n## Graceful shutdown\n\nUsing `Horde.DynamicSupervisor.stop/3` will cause the local supervisor to stop and any processes it was running will be shut down and redistributed to remaining supervisors in the horde. (This should happen automatically if `:init.stop()` is called).\n\n## Installation\n\nHorde is [available in Hex](https://hex.pm/packages/horde).\n\nThe package can be installed by adding `horde` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:horde, \"~\u003e 0.8.5\"}\n  ]\nend\n```\n\n## Usage\n\nHere is a small taste of Horde's usage. See the full docs at [https://hexdocs.pm/horde](https://hexdocs.pm/horde) for more information and examples. There is also an example application at `examples/hello_world` that you can refer to if you get stuck.\n\nStarting `Horde.DynamicSupervisor`:\n\n```elixir\ndefmodule MyApp.Application do\n  use Application\n  def start(_type, _args) do\n    children = [\n      {Horde.DynamicSupervisor, [name: MyApp.DistributedSupervisor, strategy: :one_for_one]}\n    ]\n    Supervisor.start_link(children, strategy: :one_for_one)\n  end\nend\n```\n\nAdding a child to the supervisor:\n\n```elixir\n# Add a Task\nHorde.DynamicSupervisor.start_child(MyApp.DistributedSupervisor, %{id: :task, start: {Task, :start_link, [:infinity]}})\n\n# Add an Agent\nHorde.DynamicSupervisor.start_child(MyApp.DistributedSupervisor, %{id: :agent, start: {Agent, :start_link, [fn -\u003e %{} end]}})\n\n# Add a GenServer: You need a previously defined GenServer to call the one\n# liner below.  We have a test (\"graceful shutdown\") in\n# `test/supervisor_test.exs` that exercises and displays that behavior. After\n# defined, it would be very similar to this:\nHorde.DynamicSupervisor.start_child(MyApp.DistributedSupervisor, %{id: :gen_server, start: {GenServer, :start_link, [DefinedGenServer, {500, pid}]}})\n```\n\nAnd so on. The public API should be the same as `Elixir.DynamicSupervisor` (and please open an issue if you find a difference).\n\nJoining supervisors into a single distributed supervisor can be done using `Horde.Cluster`:\n\n```elixir\n{:ok, supervisor_1} = Horde.DynamicSupervisor.start_link(name: :distributed_supervisor_1, strategy: :one_for_one)\n{:ok, supervisor_2} = Horde.DynamicSupervisor.start_link(name: :distributed_supervisor_2, strategy: :one_for_one)\n{:ok, supervisor_3} = Horde.DynamicSupervisor.start_link(name: :distributed_supervisor_3, strategy: :one_for_one)\n\nHorde.Cluster.set_members(:distributed_supervisor_1, [:distributed_supervisor_1, :distributed_supervisor_2, :distributed_supervisor_3])\n# supervisor_1, supervisor_2 and supervisor_3 will be joined in a single cluster.\n```\n\n\n# Other projects\n\nUseful libraries that use or extend Horde functionalities.\n\n## [Horde.Process](https://github.com/tyler-eon/horde-process)\n\nAn opinionated but configurable means of quickly creating GenServer modules that are intended to be managed and distributed via Horde.\n\n# Contributing\n\nContributions are welcome! Feel free to open an issue if you'd like to discuss a problem or a possible solution. Pull requests are much appreciated.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felixir-horde%2Fhorde","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felixir-horde%2Fhorde","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felixir-horde%2Fhorde/lists"}