Small Group Tutorials

Here to help students catch up, keep up, and move ahead. Book a consultation here.

How to Learn Chang–Roberts Ring Election: Unique IDs, Participant Flags, Message Suppression, Leader Announcement and Distributed-System Limits

Three students studying together in an eduKate small-group classroom.

How can a group of processes arranged in a logical ring choose exactly one leader when every process knows only its own identifier and its successor? The Chang–Roberts algorithm solves this under a clean asynchronous ring model by circulating candidate identifiers. Larger identifiers suppress smaller ones, so the maximum identifier is the only candidate that can survive a complete trip around the ring and return to its owner.

This article teaches Chang–Roberts as a Learning Hall progression from passing numbered cards around a circle to professional reasoning about message complexity, safety, liveness and failure assumptions. It complements eduKateSengkang’s broader Raft consensus article and Bully leader-election article. The job here is narrower: understand one classic election algorithm for a stable unidirectional ring, then understand exactly where that model stops being sufficient.

Quick Read

  • Processes form a unidirectional logical ring and each has a unique comparable identifier.
  • An election message carries a candidate ID around the ring.
  • A process forwards a candidate larger than its own ID.
  • A smaller candidate can be suppressed; a process that has not yet participated may replace it with its own larger ID.
  • A participant flag prevents the same process from repeatedly injecting its own candidate during one election.
  • If a process receives its own election ID, that ID has survived the whole ring and the process is the leader.
  • The leader circulates a separate leader/elected announcement so every process learns the result and resets election state.
  • The classic algorithm has O(n²) worst-case message complexity and O(n log n) average message complexity under the random-order analysis in the original paper.
  • The basic model assumes a stable ring and reliable communication; it is not by itself a modern failure-tolerant consensus protocol.

1. Beginner Level: Pass the Largest Number Around a Circle

Seat six students in a circle. Give each student a different number and allow messages to travel clockwise only. The goal is for everyone eventually to agree that the student with the largest number is leader.

A naïve solution is for every number to make a full trip around the ring. Each student could then collect all identifiers and choose the maximum. That works, but it wastes messages: obviously weak candidates continue circulating even after encountering a larger identifier.

Chang–Roberts improves the idea by letting larger IDs extinguish smaller candidate messages. The ring becomes a distributed tournament in which dominance is decided locally, yet the maximum survives globally.

2. State the Model Before Stating the Algorithm

The classic teaching model makes assumptions that are easy to forget once the pseudocode becomes familiar:

  • the processes form one unidirectional logical ring;
  • each process knows how to send to its successor;
  • identifiers are unique and totally ordered;
  • messages are delivered reliably under the algorithm’s model;
  • the membership and ring topology stay stable while the election completes;
  • processes do not crash or partition the ring during the basic correctness argument.

Those assumptions are part of the algorithm. Removing them without adding new mechanisms changes the problem.

3. What Each Process Stores

  • uid: the process’s unique identifier.
  • participant: whether the process is already participating in the current election.
  • leader: the identifier learned from the final elected/leader announcement.
  • successor: the next process in the unidirectional ring.

The participant flag is the key improvement over a simpler “always replace smaller IDs with my own ID” rule. Once a process has joined the election, it does not keep reinjecting its own identifier every time another weaker candidate arrives.

4. Starting an Election

Any process may start an election. It marks itself as a participant and sends an election message containing its own ID to its successor:

participant = true
send ELECTION(my_id) to successor

More than one process may start at about the same time. The algorithm must therefore work with multiple candidate messages in flight, not just one neatly scheduled initiator.

5. Receiving an Election Candidate

Suppose process P with identifier p receives ELECTION(x).

Case A: x > p

The incoming candidate is stronger than P’s own ID. P forwards x and marks itself as a participant. P cannot legitimately replace a larger candidate with a smaller one.

if x > my_id:
    participant = true
    forward ELECTION(x)

Case B: x < p and P is not yet a participant

P has just learned that the incoming candidate is weaker than itself, and P has not yet entered the election. It suppresses x, marks itself as a participant and sends its own larger ID instead.

if x < my_id and not participant:
    participant = true
    send ELECTION(my_id)

Case C: x < p and P is already a participant

P has already injected or forwarded election traffic. The smaller candidate is simply discarded. This is the selective message suppression that reduces unnecessary circulation.

Case D: x = p

P’s own identifier has travelled around the entire ring and returned. No larger identifier suppressed it. Therefore p is the maximum ID in the ring and P declares itself leader.

6. Why Receiving Your Own ID Is a Proof, Not a Vote Count

When process P receives ELECTION(p), the message has crossed every process in the ring. If any process had an ID q > p, that process would have prevented p from continuing unchanged. Therefore no larger ID exists.

The algorithm does not collect ballots or count preferences. The returning message is a certificate produced by traversal and suppression: p survived every comparison that the ring can perform.

7. The Election Is Not Finished Until Everyone Learns the Leader

Once the maximum-ID process sees its own candidate return, it knows it is leader. The other processes do not necessarily know that yet. The leader therefore sends a separate announcement, often written ELECTED(leader_id) or COORDINATOR(leader_id).

  • Each process records the leader ID.
  • Each process clears its participant flag.
  • Each process forwards the announcement to its successor.
  • When the announcement returns to the leader, the circulation is complete.

This distinction—leader discovery versus leader dissemination—is worth preserving in both code and reasoning.

8. A Worked Ring Trace

Take a clockwise ring with IDs:

3 → 8 → 2 → 6 → 5 → back to 3

Suppose process 3 starts. It sends 3 to process 8. Since 8 > 3 and 8 was not participating, 8 suppresses candidate 3 and sends 8. Process 2 sees 8 > 2 and forwards 8. So do processes 6, 5 and 3. Eventually candidate 8 returns to process 8.

At that point 8 knows it is the maximum identifier. It sends ELECTED(8) around the ring. Each process records 8 as leader and clears its participant state.

Now change the scenario so 3, 6 and 5 initiate nearly simultaneously. Multiple candidate messages circulate, but smaller IDs are progressively extinguished. The message carrying 8 still cannot be suppressed and will eventually complete the ring under the stable/reliable assumptions.

9. Pseudocode

START_ELECTION():
    participant = true
    send ELECTION(my_id) to successor

ON RECEIVE ELECTION(x):
    if x > my_id:
        participant = true
        forward ELECTION(x)

    else if x < my_id:
        if participant == false:
            participant = true
            send ELECTION(my_id)
        else:
            discard x

    else:  # x == my_id
        leader = my_id
        participant = false
        send ELECTED(my_id) to successor

ON RECEIVE ELECTED(x):
    leader = x
    participant = false

    if x != my_id:
        forward ELECTED(x)
    else:
        election complete

Some presentations vary small state-setting details or message names. The invariant to protect is that stronger candidates continue, weaker candidates are selectively suppressed, the maximum ID can make a complete ring traversal, and the elected announcement terminates after one full circulation.

10. A Transparent Python Event Simulation

from collections import deque


def chang_roberts(ids, initiators):
    n = len(ids)
    participant = [False] * n
    known_leader = [None] * n
    q = deque()
    messages = 0

    def successor(i):
        return (i + 1) % n

    def send(kind, value, receiver):
        nonlocal messages
        messages += 1
        q.append((kind, value, receiver))

    # Multiple processes may initiate.
    for i in initiators:
        if not participant[i]:
            participant[i] = True
            send("ELECTION", ids[i], successor(i))

    leader_index = None

    while q:
        kind, value, i = q.popleft()

        if kind == "ELECTION":
            if value > ids[i]:
                participant[i] = True
                send("ELECTION", value, successor(i))

            elif value < ids[i]:
                if not participant[i]:
                    participant[i] = True
                    send("ELECTION", ids[i], successor(i))
                # otherwise the weaker candidate is discarded

            else:  # value == ids[i]
                leader_index = i
                known_leader[i] = value
                participant[i] = False
                send("ELECTED", value, successor(i))

        else:  # ELECTED
            known_leader[i] = value
            participant[i] = False

            if i == leader_index:
                # The leader announcement has made one full ring.
                break
            send("ELECTED", value, successor(i))

    return {
        "leader_id": None if leader_index is None else ids[leader_index],
        "known_leader": known_leader,
        "messages": messages,
    }


print(chang_roberts([3, 8, 2, 6, 5], initiators=[0, 3, 4]))

This simulator deliberately models messages as queued events rather than function calls. That makes the distributed nature visible: local state changes when a message is delivered, not because one central recursive procedure “knows” the whole ring.

11. Safety: Why There Can Be Only One Leader Under the Model

Assume unique IDs and one stable ring. Let M be the maximum identifier. No process can suppress ELECTION(M), because no process has a larger ID. Therefore M’s candidate can traverse the whole ring once injected.

Now consider any smaller identifier x. Before x could return to its origin, it would have to pass the process whose ID is M. That process does not forward x unchanged: it suppresses x. Therefore x cannot complete an unmodified full traversal and cannot satisfy the “my own ID returned” leader condition.

Thus, under the assumptions, only the maximum-ID process can declare itself leader.

12. Liveness: Why the Maximum Eventually Wins

Safety says a wrong process cannot legitimately win. Liveness asks whether the correct leader eventually does win. Under reliable delivery, stable membership and continued process execution, the maximum identifier is eventually introduced into the election—either because its owner initiates or because its owner receives a smaller candidate while not yet participating.

Once in flight, M cannot be suppressed. Reliable message delivery eventually carries it around the ring and back to its owner, which then sends the leader announcement.

This separation of safety and liveness is professional distributed-systems reasoning. An implementation can preserve safety while losing liveness under message loss, or make progress while risking split-brain if failure assumptions are handled incorrectly.

13. Message Complexity: Count Communications, Not Just Comparisons

In a distributed algorithm, a local comparison may be cheap while a network message is expensive. Chang and Roberts designed their improvement to suppress unnecessary candidate circulation.

The classic analysis gives:

  • worst-case message complexity: O(n²);
  • average message complexity: O(n log n) for the identifier-order model analysed in the original paper;
  • leader announcement: an additional O(n) messages.

The O(n²) worst case appears when the identifier ordering lets many candidates travel a long way before encountering a larger ID. Later ring-election algorithms improve the worst-case message bound, but Chang–Roberts remains valuable because its mechanism is easy to see and prove.

14. Time Complexity Is Not the Same as Message Complexity

Counting messages answers “how much communication?” It does not fully answer “how long until election completes?” In an asynchronous system, elapsed time depends on message delay and scheduling. In a synchronous round model, one can reason about traversals in rounds. In real networks, latency distributions, queuing and retries matter.

Professionals therefore state the cost model explicitly: messages, bytes, local operations, rounds, wall-clock latency or some combination.

15. Why the Participant Flag Matters

Imagine process 9 has already entered an election. Later it receives candidate 4. If it injects 9 again every time it sees a smaller identifier, the ring can accumulate redundant copies of the same candidate. The participant flag says, in effect, “I have already entered this election; there is no need to restart my candidacy because of this weaker message.”

This is a useful distributed-design pattern: a small piece of local state can suppress repeated work without requiring a global coordinator.

16. Chang–Roberts Is Leader Election, Not Consensus

Leader election answers a narrow question: which process should currently be designated leader under the algorithm’s model? Consensus protocols address a harder problem: how multiple processes agree on values or replicated history despite failures and asynchronous communication constraints.

Raft includes leader election, but its terms, log-matching rules, majority quorums and commit conditions exist because replicated-state-machine consensus requires much more than choosing the largest ID in a ring. Do not infer that a ring-election algorithm can replace Raft or Paxos.

17. The Basic Algorithm’s Failure Boundary

The elegant proof depends on the ring remaining a ring. If a process crashes and its predecessor cannot route around it, a candidate may never complete the traversal. If the network partitions into two independently operating regions, each region may make progress under a modified local view and create conflicting leadership unless the system adds quorum, membership, epoch or fencing mechanisms.

  • Node crash: may break the successor chain.
  • Link failure: can prevent messages from completing the ring.
  • Partition: destroys the assumption of one connected election domain.
  • Membership change: raises the question of which ring the proof refers to.
  • Duplicate/stale messages: require election-instance or epoch handling in practical extensions.
  • Recovered old leader: may need fencing so stale authority cannot overwrite current work.

These are not criticisms of the original algorithm. They mark the boundary of the problem it was designed to solve.

18. Professional Engineering: Add the Missing Operational State Explicitly

If a real system adapts ring election ideas, it typically needs mechanisms outside the classic core:

  • membership/version identifiers so all participants know which configuration is being elected;
  • failure detection or timeout policy;
  • routing around failed members, if the topology permits it;
  • election epochs or terms to reject stale messages;
  • fencing tokens or authority checks so an old leader cannot act after replacement;
  • observability for election start, message flow, suppression, completion and repeated elections;
  • backoff or rate limiting to prevent election storms.

At that point the engineer should ask whether preserving the ring-election design is still appropriate, or whether a mature coordination/consensus protocol already matches the system requirements better.

19. Failure Modes Strong Learners Should Test

  • Non-unique IDs: two processes can satisfy an equality condition for the same identifier, invalidating the uniqueness proof.
  • Forgetting participant state: processes may repeatedly reinject their own candidates.
  • Dropping the leader announcement: one process knows it won while others retain stale leader state.
  • Forwarding the elected message forever: the leader needs a termination condition when its announcement returns.
  • Assuming FIFO without stating it: if an implementation depends on channel order, make that dependency explicit.
  • Node crash during election: liveness can disappear even though the local comparison logic remains correct.
  • Partitioned ring: “the maximum ID” is undefined unless the membership view is agreed.
  • Stale election instance: old traffic can overwrite newer leadership if elections are not versioned in an extended system.
  • Counting only CPU operations: message cost is often the dominant resource.

20. Testing a Ring-Election Implementation

Start with deterministic simulations before introducing real networking. Generate every permutation of small unique-ID rings and vary the initiating set. Check these invariants:

  • the elected ID equals max(ids);
  • all processes eventually record the same leader under the reliable stable-ring model;
  • all participant flags return to false after completion;
  • no smaller candidate can return to its origin unchanged;
  • the leader announcement circulates exactly once after declaration;
  • message counts match hand traces on tiny rings.

Then introduce controlled faults in a simulator—message loss, process pause, duplicated messages, ring reconfiguration—not to claim the classic algorithm handles them, but to reveal precisely which assumption each fault violates.

21. Learning Progression: Beginner to Professional

  • Beginner: pass ID cards around a physical circle and suppress smaller cards when they encounter larger IDs.
  • Intermediate: trace simultaneous initiators and annotate participant flags after each message delivery.
  • Advanced: build an event-driven simulator, measure message counts across ID permutations and prove safety/liveness separately.
  • Professional: inject failures, identify which assumptions break, compare with other election and consensus protocols, and design explicit membership/epoch/fencing rules before considering deployment.

A productive teaching sequence is Predict–Run–Investigate–Modify: predict which candidate will be suppressed next, run one event, inspect process state, then modify the initiator set or identifier ordering. Subgoal-labelled worked examples also fit naturally: identify the message type, compare IDs, inspect participant state, choose the local action, then update the global trace.

22. Practice Problems

  • Trace a ring with IDs 4→1→7→3→6 when only process 1 initiates.
  • Repeat when every process initiates simultaneously. Count every election and elected message.
  • Find an identifier ordering that creates many long-lived candidates and explain why the worst-case cost approaches quadratic.
  • Remove the participant flag from the simulator and measure how message traffic changes.
  • Prove that the maximum ID cannot be suppressed by any valid election-message rule.
  • Pause one process indefinitely. Which liveness step fails?
  • Split a six-node ring into two disconnected three-node rings. Explain why “one global leader” no longer follows from the classic proof.
  • Add an election epoch to the teaching simulator and reject messages from older epochs.
  • Compare Chang–Roberts with the Bully algorithm: what topology knowledge and failure assumptions differ?

23. Sources and Further Reading

Final idea: Chang–Roberts is valuable because one local rule—forward stronger identifiers, extinguish weaker ones—creates a global winner without any process initially knowing the whole ring. Its deeper lesson is equally important: a distributed algorithm’s proof is inseparable from its communication, membership and failure assumptions. Knowing the boundary of the proof is part of knowing the algorithm.