{"id":15056382,"url":"https://github.com/rabbitmq/ra","last_synced_at":"2026-04-21T08:03:51.707Z","repository":{"id":27378009,"uuid":"82831082","full_name":"rabbitmq/ra","owner":"rabbitmq","description":"A Multi-Raft implementation for Erlang and Elixir that strives to be efficient and make it easier to use multiple Raft clusters in a single system.","archived":false,"fork":false,"pushed_at":"2026-04-01T15:51:27.000Z","size":21298,"stargazers_count":933,"open_issues_count":30,"forks_count":108,"subscribers_count":38,"default_branch":"main","last_synced_at":"2026-04-03T01:43:19.401Z","etag":null,"topics":["distributed-systems","erlang","raft","raft-consensus-algorithm"],"latest_commit_sha":null,"homepage":"","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rabbitmq.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-02-22T17:07:57.000Z","updated_at":"2026-04-01T15:49:51.000Z","dependencies_parsed_at":"2026-01-03T03:05:37.428Z","dependency_job_id":null,"html_url":"https://github.com/rabbitmq/ra","commit_stats":{"total_commits":1327,"total_committers":45,"mean_commits":"29.488888888888887","dds":0.4611906556141673,"last_synced_commit":"13c6f7422705c1327f8280690cf4706f3b6aa534"},"previous_names":[],"tags_count":131,"template":false,"template_full_name":null,"purl":"pkg:github/rabbitmq/ra","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rabbitmq%2Fra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rabbitmq%2Fra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rabbitmq%2Fra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rabbitmq%2Fra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rabbitmq","download_url":"https://codeload.github.com/rabbitmq/ra/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rabbitmq%2Fra/sbom","scorecard":{"id":757275,"data":{"date":"2025-08-11","repo":{"name":"github.com/rabbitmq/ra","commit":"3df59d0a8920716d0ac43f918d96d0a0e0d1b7dd"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":6.2,"checks":[{"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":"Code-Review","score":6,"reason":"Found 8/13 approved changesets -- score normalized to 6","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":10,"reason":"30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/erlang.yml:1","Warn: no topLevel permission defined: .github/workflows/release.yml:1","Warn: no topLevel permission defined: .github/workflows/trigger-jepsen.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":"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":"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":"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":"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":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"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":"Fuzzing","score":10,"reason":"project is fuzzed","details":["Info: ErlangPropertyBasedTesting integration found: test/partitions_SUITE.erl:12","Info: ErlangPropertyBasedTesting integration found: test/ra_log_props_SUITE.erl:11","Info: ErlangPropertyBasedTesting integration found: test/ra_props_SUITE.erl:12","Info: ErlangPropertyBasedTesting integration found: test/partitions_SUITE.erl:12","Info: ErlangPropertyBasedTesting integration found: test/ra_log_props_SUITE.erl:11","Info: ErlangPropertyBasedTesting integration found: test/ra_props_SUITE.erl:12"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/rabbitmq/.github/SECURITY.md:1","Info: Found linked content: github.com/rabbitmq/.github/SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: github.com/rabbitmq/.github/SECURITY.md:1","Info: Found text in security policy: github.com/rabbitmq/.github/SECURITY.md:1"],"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":"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/erlang.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/rabbitmq/ra/erlang.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/erlang.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/rabbitmq/ra/erlang.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/erlang.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/rabbitmq/ra/erlang.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/rabbitmq/ra/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/rabbitmq/ra/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/rabbitmq/ra/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/trigger-jepsen.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/rabbitmq/ra/trigger-jepsen.yml/main?enable=pin","Info:   0 out of   3 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 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":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v2.17.0 not signed: https://api.github.com/repos/rabbitmq/ra/releases/233949127","Warn: release artifact v2.16.12 not signed: https://api.github.com/repos/rabbitmq/ra/releases/233863169","Warn: release artifact v2.16.11 not signed: https://api.github.com/repos/rabbitmq/ra/releases/227352128","Warn: release artifact v2.16.10 not signed: https://api.github.com/repos/rabbitmq/ra/releases/222698209","Warn: release artifact v2.17.0 does not have provenance: https://api.github.com/repos/rabbitmq/ra/releases/233949127","Warn: release artifact v2.16.12 does not have provenance: https://api.github.com/repos/rabbitmq/ra/releases/233863169","Warn: release artifact v2.16.11 does not have provenance: https://api.github.com/repos/rabbitmq/ra/releases/227352128","Warn: release artifact v2.16.10 does not have provenance: https://api.github.com/repos/rabbitmq/ra/releases/222698209"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 26 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-22T22:04:08.030Z","repository_id":27378009,"created_at":"2025-08-22T22:04:08.031Z","updated_at":"2025-08-22T22:04:08.031Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31842193,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-15T11:29:19.690Z","status":"ssl_error","status_checked_at":"2026-04-15T11:29:19.171Z","response_time":63,"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":["distributed-systems","erlang","raft","raft-consensus-algorithm"],"created_at":"2024-09-24T21:50:24.791Z","updated_at":"2026-04-15T13:01:18.104Z","avatar_url":"https://github.com/rabbitmq.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ra: A Raft Implementation for Erlang and Elixir\n\n[![Hex.pm](https://img.shields.io/hexpm/v/ra)](https://hex.pm/packages/ra/)\n![Actions](https://github.com/rabbitmq/ra/actions/workflows/erlang.yml/badge.svg)\n\nRa is a [Raft](https://raft.github.io/) implementation\nby Team RabbitMQ. It is not tied to RabbitMQ and can be used in any Erlang or Elixir\nproject. It is, however, heavily inspired by and geared towards RabbitMQ needs.\n\nRa (by virtue of being a Raft implementation) is a library that allows users to implement [persistent, fault-tolerant and replicated state machines](https://en.wikipedia.org/wiki/State_machine_replication).\n\n## Project Maturity\n\nThis library has been extensively tested and is suitable for production use.\nThis means the primary APIs (`ra`, `ra_machine` modules) and on disk formats\nwill be backwards-compatible going forwards in line with Semantic Versioning.\nCare has been taken to version all on-disk data formats to enable frictionless\nfuture upgrades.\n\n### Status\n\nThe following Raft features are implemented:\n\n * Leader election\n * Log replication\n * Cluster membership changes: one server (member) at a time\n * Log compaction (with limitations and RabbitMQ-specific extensions)\n * Snapshot installation\n\n### Safety Verification\n\nRa is [continuously tested](https://github.com/rabbitmq/ra-kv-store#jepsen-test) with the [Jepsen](https://github.com/jepsen-io/jepsen)\ndistributed system verification framework.\n\n## Supported Erlang/OTP Versions\n\nRa supports the following Erlang/OTP versions:\n\n * `27.x`\n * `26.x`\n\nModern Erlang releases provide [distribution traffic fragmentation](https://www.erlang.org/blog/otp-22-highlights/#fragmented-distribution-messages)\nwhich algorithms such as Raft significantly benefit from.\n\n\n## Design Goals\n\n * Low footprint: use as few resources as possible, avoid process tree explosion\n * Able to run thousands of `ra` clusters within an Erlang node\n * Provide adequate performance for use as a basis for a distributed data service\n\n## Use Cases\n\nThis library was primarily developed as the foundation of a replication layer for\n[quorum queues](https://rabbitmq.com/quorum-queues.html) in RabbitMQ, and today\nalso powers [RabbitMQ streams](https://rabbitmq.com/streams.html) and [Khepri](https://github.com/rabbitmq/khepri).\n\nThe design it aims to replace uses\na variant of [Chain Based Replication](https://www.cs.cornell.edu/home/rvr/papers/OSDI04.pdf)\nwhich has two major shortcomings:\n\n * Replication algorithm is linear\n * Failure recovery procedure requires expensive topology changes\n\n## Smallest Possible Usage Example\n\nThe example below assumes a few things:\n\n * You are familiar with the basics of [distributed Erlang](https://learnyousomeerlang.com/distribunomicon)\n * Three Erlang nodes are started on the local machine or reachable resolvable hosts.\n   Their names are `ra1@hostname.local`, `ra2@hostname.local`, and `ra3@hostname.local` in the example below but your actual hostname will be different.\n   Therefore the naming scheme is `ra{N}@{hostname}`. This is not a Ra requirement so you are\n   welcome to use different node names and update the code accordingly.\n\nErlang nodes can be started using `rebar3 shell --name {node name}`. They will have Ra modules\non code path:\n\n``` shell\n# replace hostname.local with your actual hostname\nrebar3 shell --name ra1@hostname.local\n```\n\n``` shell\n# replace hostname.local with your actual hostname\nrebar3 shell --name ra2@hostname.local\n```\n\n``` shell\n# replace hostname.local with your actual hostname\nrebar3 shell --name ra3@hostname.local\n```\n\nAfter Ra nodes form a cluster, state machine commands can be performed.\n\nHere's what a small example looks like:\n\n``` erlang\n%% All servers in a Ra cluster are named processes on Erlang nodes.\n%% The Erlang nodes must have distribution enabled and be able to\n%% communicate with each other.\n%% See https://learnyousomeerlang.com/distribunomicon if you are new to Erlang/OTP.\n\n%% These Erlang nodes will host Ra nodes. They are the \"seed\" and assumed to\n%% be running or come online shortly after Ra cluster formation is started with ra:start_cluster/4.\nErlangNodes = ['ra1@hostname.local', 'ra2@hostname.local', 'ra3@hostname.local'],\n\n%% This will check for Erlang distribution connectivity. If Erlang nodes\n%% cannot communicate with each other, Ra nodes would not be able to cluster or communicate\n%% either.\n[io:format(\"Attempting to communicate with node ~s, response: ~s~n\", [N, net_adm:ping(N)]) || N \u003c- ErlangNodes],\n\n%% The Ra application has to be started on all nodes before it can be used.\n[rpc:call(N, ra, start, []) || N \u003c- ErlangNodes],\n\n%% Create some Ra server IDs to pass to the configuration. These IDs will be\n%% used to address Ra nodes in Ra API functions.\nServerIds = [{quick_start, N} || N \u003c- ErlangNodes],\n\nClusterName = quick_start,\n%% State machine that implements the logic and an initial state\nMachine = {simple, fun erlang:'+'/2, 0},\n\n%% Start a Ra cluster with an addition state machine that has an initial state of 0.\n%% It's sufficient to invoke this function only on one Erlang node. For example, this\n%% can be a \"designated seed\" node or the node that was first to start and did not discover\n%% any peers after a few retries.\n%%\n%% Repeated startup attempts will fail even if the cluster is formed, has elected a leader\n%% and is fully functional.\n{ok, ServersStarted, _ServersNotStarted} = ra:start_cluster(default, ClusterName, Machine, ServerIds),\n\n%% Add a number to the state machine.\n%% Simple state machines always return the full state after each operation.\n{ok, StateMachineResult, LeaderId} = ra:process_command(hd(ServersStarted), 5),\n\n%% Use the leader id from the last command result for the next one\n{ok, 12, LeaderId1} = ra:process_command(LeaderId, 7).\n```\n\n### Querying Machine State\n\nRa machines are only useful if their state can be queried. There are two types of queries:\n\n * Local queries return machine state on the target node\n * Leader queries return machine state from the leader node.\n   If a follower node is queried, the query command will be redirected to the leader.\n\nLocal queries are much more efficient but can return out-of-date machine state.\nLeader queries offer best possible machine state consistency but potentially require\nsending a request to a remote node.\n\nUse `ra:leader_query/{2,3}` to perform a leader query:\n\n``` erlang\n%% find current Raft cluster leader\n{ok, _Members, LeaderId} = ra:members(quick_start),\n%% perform a leader query on the leader node\nQueryFun = fun(StateVal) -\u003e StateVal end,\n{ok, {_TermMeta, State}, LeaderId1} = ra:leader_query(LeaderId, QueryFun).\n```\n\nSimilarly, use `ra:local_query/{2,3}` to perform a local query:\n\n``` erlang\n%% this is the replica hosted on the current Erlang node.\n%% alternatively it can be constructed as {ClusterName, node()}\n{ok, Members, _LeaderId} = ra:members(quick_start),\nLocalReplicaId = lists:keyfind(node(), 2, Members),\n%% perform a local query on the local node\nQueryFun = fun(StateVal) -\u003e StateVal end,\n{ok, {_TermMeta, State}, LeaderId1} = ra:local_query(LocalReplicaId, QueryFun).\n```\n\nA query function is a single argument function that accepts current machine state\nand returns any value (usually derived from the state).\n\nBoth `ra:leader_query/2` and `ra:local_query/2` return machine term metadata, a result returned by the query\nfunction, and current cluster leader ID.\n\n\n### Dynamically Changing Cluster Membership\n\nNodes can be added to or removed from a Ra cluster dynamically. Only one\ncluster membership change at a time is allowed: concurrent changes\nwill be rejected by design.\n\nIn this example, instead of starting a \"pre-formed\" cluster,\na local server is started and then members are added by calling `ra:add_member/2`.\n\nStart 3 Erlang nodes:\n\n``` shell\n# replace hostname.local with your actual hostname\nrebar3 shell --name ra1@hostname.local\n```\n\n``` shell\n# replace hostname.local with your actual hostname\nrebar3 shell --name ra2@hostname.local\n```\n\n``` shell\n# replace hostname.local with your actual hostname\nrebar3 shell --name ra3@hostname.local\n```\n\nStart the ra application:\n\n``` erlang\n%% on ra1@hostname.local\nra:start().\n% =\u003e ok\n```\n\n``` erlang\n%% on ra2@hostname.local\nra:start().\n% =\u003e ok\n```\n\n``` erlang\n%% on ra3@hostname.local\nra:start().\n% =\u003e ok\n```\n\nA single node cluster can be started from any node.\n\nFor the purpose of this example, `ra2@hostname.local` is used as the starting member:\n\n``` erlang\nClusterName = dyn_members,\nMachine = {simple, fun erlang:'+'/2, 0},\n\n% Start a cluster\n{ok, _, _} =  ra:start_cluster(default, ClusterName, Machine, [{dyn_members, 'ra2@hostname.local'}]).\n```\n\nAfter the cluster is formed, members can be added.\n\nAdd `ra1@hostname.local` by telling `ra2@hostname.local` about it\nand starting a Ra replica (server) on `ra1@hostname.local` itself:\n\n``` erlang\n% Add member\n{ok, _, _} = ra:add_member({dyn_members, 'ra2@hostname.local'}, {dyn_members, 'ra1@hostname.local'}),\n\n% Start the server\nok = ra:start_server(default, ClusterName, {dyn_members, 'ra1@hostname.local'}, Machine, [{dyn_members, 'ra2@hostname.local'}]).\n```\n\nAdd `ra3@hostname.local` to the cluster:\n\n``` erlang\n% Add a new member\n{ok, _, _} = ra:add_member({dyn_members, 'ra2@hostname.local'}, {dyn_members, 'ra3@hostname.local'}),\n\n% Start the server\nok = ra:start_server(default, ClusterName, {dyn_members, 'ra3@hostname.local'}, Machine, [{dyn_members, 'ra2@hostname.local'}]).\n```\n\nCheck the members from any node:\n\n``` erlang\nra:members({dyn_members, node()}).\n% =\u003e {ok,[{dyn_members,'ra1@hostname.local'},\n% =\u003e      {dyn_members,'ra2@hostname.local'},\n% =\u003e      {dyn_members,'ra3@hostname.local'}],\n% =\u003e      {dyn_members,'ra2@hostname.local'}}\n```\n\nIf a node wants to leave the cluster, it can use `ra:leave_and_terminate/3`\nand specify itself as the target:\n\nTemporarily add a new node, say `ra4@hostname.local`, to the cluster:\n\n``` erlang\n% Add a new member\n{ok, _, _} = ra:add_member({dyn_members, 'ra2@hostname.local'}, {dyn_members, 'ra4@hostname.local'}),\n\n% Start the server\nok = ra:start_server(default, ClusterName, {dyn_members, 'ra4@hostname.local'}, Machine, [{dyn_members, 'ra2@hostname.local'}]).\n\n%% on ra4@hostname.local\nra:leave_and_terminate(default, {ClusterName, node()}, {ClusterName, node()}).\n\nra:members({ClusterName, node()}).\n% =\u003e {ok,[{dyn_members,'ra1@hostname.local'},\n% =\u003e      {dyn_members,'ra2@hostname.local'},\n% =\u003e      {dyn_members,'ra3@hostname.local'}],\n% =\u003e      {dyn_members,'ra2@hostname.local'}}\n```\n\n### Other examples\n\nSee [Ra state machine tutorial](docs/internals/STATE_MACHINE_TUTORIAL.md)\nfor how to write more sophisticated state machines by implementing\nthe `ra_machine` behaviour.\n\nA [Ra-based key/value store example](https://github.com/rabbitmq/ra-kv-store)\nis available in a separate repository.\n\n\n## Documentation\n\n* [API reference](https://hex.pm/packages/ra)\n* How to write a Ra state machine: [Ra state machine tutorial](docs/internals/STATE_MACHINE_TUTORIAL.md)\n* Design and implementation details: [Ra internals guide](docs/internals/INTERNALS.md)\n\n### Examples\n\n* [Ra-based key/value store](https://github.com/rabbitmq/ra-kv-store)\n\n\n## Configuration Reference\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eKey\u003c/td\u003e\n        \u003ctd\u003eDescription\u003c/td\u003e\n        \u003ctd\u003eData Type\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003edata_dir\u003c/td\u003e\n        \u003ctd\u003eA directory name where Ra node will store its data\u003c/td\u003e\n        \u003ctd\u003eLocal directory path\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewal_data_dir\u003c/td\u003e\n        \u003ctd\u003e\n            A directory name where Ra will store it's WAL (Write Ahead Log) data.\n            If unspecified, `data_dir` is used.\n        \u003c/td\u003e\n        \u003ctd\u003eLocal directory path\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewal_max_size_bytes\u003c/td\u003e\n        \u003ctd\u003eThe maximum size of the WAL in bytes. Default: 512 MB\u003c/td\u003e\n        \u003ctd\u003ePositive integer\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewal_max_entries\u003c/td\u003e\n        \u003ctd\u003eThe maximum number of entries per WAL file. Default: undefined\u003c/td\u003e\n        \u003ctd\u003ePositive integer\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewal_compute_checksums\u003c/td\u003e\n        \u003ctd\u003eIndicate whether the wal should compute and validate checksums. Default: `true`\u003c/td\u003e\n        \u003ctd\u003eBoolean\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewal_sync_method\u003c/td\u003e\n        \u003ctd\u003e\n            \u003cul\u003e\n                \u003cli\u003e\n                    \u003ccode\u003edatasync\u003c/code\u003e: used by default. Uses the \u003ccode\u003efdatasync(2)\u003c/code\u003e system call after each batch. This avoids flushing\n                    file meta-data after each write batch and thus may be slightly faster than sync on some system. When datasync is configured the wal will try to pre-allocate the entire WAL file.\n                    Not all systems support \u003ccode\u003efdatasync\u003c/code\u003e. Please consult system\n                    documentation and configure it to use sync instead if it is not supported.\n                \u003c/li\u003e\n                \u003cli\u003e\n                    \u003ccode\u003esync\u003c/code\u003e: uses the fsync system call after each batch.\n                \u003c/li\u003e\n            \u003c/ul\u003e\n        \u003c/td\u003e\n        \u003ctd\u003eEnumeration: \u003ccode\u003edatasync\u003c/code\u003e | \u003ccode\u003esync\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003elogger_module\u003c/td\u003e\n        \u003ctd\u003e\n            Allows the configuration of a custom logger module. The default is logger.\n            The module must implement a function of the same signature\n            as \u003ca href=\"http://erlang.org/doc/man/logger.html#log-4\"\u003elogger:log/4\u003c/a\u003e (the variant that takes a format not the variant that takes a function).\n        \u003c/td\u003e\n        \u003ctd\u003eAtom\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewal_max_batch_size\u003c/td\u003e\n        \u003ctd\u003e\n            Controls the internal max batch size that the WAL will accept.\n            Higher numbers may result in higher memory use. Default: 32768.\n        \u003c/td\u003e\n        \u003ctd\u003ePositive integer\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewal_hibernate_after\u003c/td\u003e\n        \u003ctd\u003e\n            Enables hibernation after a timeout of inactivity for the WAL process.\n        \u003c/td\u003e\n        \u003ctd\u003eMilliseconds\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003emetrics_key\u003c/td\u003e\n        \u003ctd\u003eDEPRECATED: Metrics key. The key was used to write metrics into the ra_metrics table. Metrics are now in Seshat.\u003c/td\u003e\n        \u003ctd\u003eAtom\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003emetrics_labels\u003c/td\u003e\n        \u003ctd\u003eMetrics labels. Labels that are later returned with metrics for this server (eg. `#{vhost =\u003e ..., queue =\u003e ...}` for quorum queues).\u003c/td\u003e\n        \u003ctd\u003eMap\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003elow_priority_commands_flush_size\u003c/td\u003e\n        \u003ctd\u003e\n            When commands are pipelined using the low priority mode Ra tries to hold them\n            back in favour of normal priority commands. This setting determines the number\n            of low priority commands that are added to the log each flush cycle. Default: 25\n        \u003c/td\u003e\n        \u003ctd\u003ePositive integer\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003esegment_compute_checksums\u003c/td\u003e\n        \u003ctd\u003eIndicate whether the segment writer should compute and validate checksums. Default: `true`\u003c/td\u003e\n        \u003ctd\u003eBoolean\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n## Logging\n\nRa will use default OTP `logger` by default, unless `logger_module`\nconfiguration key is used to override.\n\nTo change log level to `debug` for all applications, use\n\n``` erl\nlogger:set_primary_config(level, debug).\n```\n\n## Ra versioning\n\nRa attempts to follow [Semantic Versioning](https://semver.org/).\n\nThe modules that form part of the public API are:\n\n* `ra`\n* `ra_machine` (behaviour callbacks only)\n* `ra_aux`\n* `ra_system`\n* `ra_counters` (counter keys may vary between minors)\n* `ra_leaderboard`\n* `ra_env`\n* `ra_directory`\n* `ra_flru`\n* `ra_log_read_plan`\n\n## Copyright and License\n\n(c) 2017-2025 Broadcom. All Rights Reserved. The term \"Broadcom\" refers to\nBroadcom Inc. and/or its subsidiaries.\n\nDual licensed under the Apache License Version 2.0 and\nMozilla Public License Version 2.0.\n\nThis means that the user can consider the library to be licensed under\n**any of the licenses from the list** above. For example, you may\nchoose the Apache Public License 2.0 and include this library into a\ncommercial product.\n\nSee [LICENSE](./LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frabbitmq%2Fra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frabbitmq%2Fra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frabbitmq%2Fra/lists"}