Structures

G-counter

The ranger asks Alice, Bob, and Carol to count birds on three trails. Each hiker tracks their own sightings in a shared three-row format, then leaves notes with their name and running count. The notes may arrive late, out of order, or more than once. By the end of the hike, all three notebooks must show the same total.

Three hikers copy the same notebook

Each notebook has one row for Alice, one for Bob, and one for Carol. A hiker writes new sightings in their own row. The other rows record the latest running counts received from checkpoint notes.

Row Alice's notebook Bob's notebook Carol's notebook
Alice700
Bob030
Carol000
Birds seen730
Before the first notes arrive, each hiker knows only their own running count.

Alice does not send seven separate sightings. She leaves one cumulative note that says her row has reached 7. Bob leaves the same kind of note when his row reaches 3.

AliceRunning bird count7

BobRunning bird count3

Three trail notebooks merge into one G-counter A B C TRAIL NOTEBOOK ALICE KEEP MAX 7 BOB KEEP MAX 3 CAROL KEEP MAX 0 BIRDS SEEN 10
Each hiker owns one row. Merge keeps the largest value in every row, then adds the rows.

Alice fills in her row

Alice takes the ridge trail. Each time she spots a bird, she adds one to her row. After seven sightings, Alice's notebook reads [Alice: 7, Bob: 0, Carol: 0], so her local total is 7.

Alice's local copy of the shared counter is a replica. Bob and Carol each keep their own replica. The hikers exchange cumulative messages by leaving notes at known checkpoints.

birds = count[Alice]

Bob takes a different trail

Bob counts birds along the river trail. Alice changes only Alice's count, and Bob changes only Bob's count. If Alice has seen 7 birds and Bob has seen 3, their shared total is 10.

This is a grow-only counter, or G-counter. Each replica keeps the largest note it has received from each hiker, then adds those counts. It does not add every message. If Bob leaves the same checkpoint note twice, both messages contain the same count of 3 birds. His count stays 3.

count[Alice] = max(all notes from Alice)
count[Bob] = max(all notes from Bob)
birds = count[Alice] + count[Bob] + ...

Their checkpoint notes cross

When a hiker finds a note, they copy its running count into the named row only if the number is larger than the count already there. The three rows add up to the bird count.

On Carol's route, the first note at the north fork is from Alice: 7 birds. At the river bridge, she finds Bob's note for 3. Carol has not seen a bird herself, so her own row stays at 0.

Checkpoint and note Alice Bob Carol Total
Trailhead0000
North fork: Alice 77007
River bridge: Bob 373010
Old lookout: Alice 473010
Carol updates her notebook as she reaches each checkpoint.

At the old lookout, Carol finds an earlier note from Alice with a count of 4. Her notebook already contains 7, so she leaves that row alone: max(7, 4) = 7. Had she found 4 first, the row would have changed from 0 to 4, then from 4 to 7. Either path through the notes leads to the same notebook and the same total.

Elsewhere on the trails, the three notebooks can still disagree. Alice may know only her 7, Bob only his 3, and Carol neither. Walk the next part with them: leave one note at a time, or let Alice and Bob leave their notes together.

Count birds on three hikes

Record birds for Alice, Bob, or Carol. Each hiker leaves their running count at a known checkpoint. Turn off Auto-deliver to hold several notes before delivery to the other checkpoints.

Merge rule Keep the largest bird count left by each hiker.

New note In transit to a checkpoint

Shared note Being delivered to the other hikers

Alice

Connected to checkpoint network

0

Birds in this hiker's view

Bob

Connected to checkpoint network

0

Birds in this hiker's view

Carol

Connected to checkpoint network

0

Birds in this hiker's view

Known checkpoint 0 notes
  1. No checkpoint note shared yet.

Enable JavaScript to run the demo. The initial values and expected result remain available in the article.

Count birds with Alice, Bob, or Carol, or leave Alice's and Bob's checkpoint notes together.

Open the hikers' count tables

Each hiker's notebook has one row for Alice, Bob, and Carol. A row stores the largest count received from that hiker. Checkpoint notes can be delivered in any order.

Hiker Alice's view Bob's view Carol's view
Alice 000
Bob 000
Carol 000

A repeated or older note cannot lower a row. Each hiker compares the note with the count already in the table and keeps the larger value.

Every trail catches up

After delivery of both checkpoint notes, Alice, Bob, and Carol all read 10. Their views were temporarily inconsistent, but the G-counter kept both hikers' observations and made every replica agree.

This is eventual consistency. For each hiker, merge keeps the larger count from their checkpoint notes. The rule is commutative, associative, and idempotent. Arrival order does not change the answer, and the network can deliver the same checkpoint note more than once.

The count cannot go down

Every hiker needs a unique replica ID. If two hikers share an ID, pairwise maximum can discard one concurrent update.

The merge rule can only keep or raise each component. If a hiker finds a counting mistake, lowering a component is unsafe because an older, larger note could restore the mistake. The next structure records corrections without changing this merge rule.

Sources and implementation

This lesson calls Watershed's public G-counter kernel. The G-counter merge rule keeps the largest cumulative count for each hiker.

The merge rule is the state-based grow-only counter described in A comprehensive study of Convergent and Commutative Replicated Data Types.