Structures

PN-counter

Alice, Bob, and Carol have agreed on 10 birds. Then Alice finds 3 more while Bob finds a duplicate sighting. Their G-counter notebooks cannot erase a count, so each hiker adds a second grow-only table for corrections.

Each hiker carries the same two-page notebook

The first page is the positive counter, or P. It records new bird sightings. The second page is the negative counter, or N. It records sightings that must be subtracted. Each page has one row that only Alice fills in, one for Bob, and one for Carol.

Notebook page Row Starting value
Sightings (P)Agreed count10
Sightings (P)Alice0
Sightings (P)Bob0
Sightings (P)Carol0
Corrections (N)Alice0
Corrections (N)Bob0
Corrections (N)Carol0
Every hiker starts with the same 10 sightings and no corrections. The visible bird count is the sightings total minus the corrections total.

Alice writes 3 in her row on the sightings page. Bob writes 1 in his row on the corrections page. The note does not ask another hiker to apply +3 or -1 again. It reports the page, the row, and the cumulative value now written there.

Alice Sightings page · Alice row 3

Bob Corrections page · Bob row 1

Concurrent sightings and corrections merge into one PN-counter CORRECTED FIELD LOG SIGHTINGS 10 + 3 13 CORRECTIONS 1 BIRDS SEEN 12 +3 -1
Alice's new sightings and Bob's correction remain separate. Every replica subtracts the correction total from the sightings total.

Add a second G-counter

Bob spots a mistake: one line records the same bird twice. The shared count must fall by one.

A G-counter component can only grow. Bob cannot lower his component because an older note with the larger value could arrive later and restore the mistake.

A PN-counter records the correction in a second G-counter. The positive counter records sightings. The negative counter records corrections. Both counters still grow and merge each hiker's component by maximum.

P = sightings G-counter
N = corrections G-counter
birds = P - N

The hikers count in both directions without making either G-counter count backward. They increment P for a new bird and increment N for a correction.

Alice and Bob fill in different pages

Neither hiker has received the other's note. Alice's notebook has 13 sightings and no corrections, so she reads 13. Bob's has 10 sightings and 1 correction, so he reads 9. Carol has not found either note, so she still reads 10.

Notebook entry Alice Bob Carol
Agreed sightings101010
Alice sightings row300
Bob corrections row010
Birds seen (P - N)13910

When both notes arrive, every notebook contains 3 in Alice's sightings row and 1 in Bob's corrections row. The notes can arrive in either order: 10 + 3 - 1 and 10 - 1 + 3 both equal 12. Each page keeps the G-counter merge rule, so a hiker who finds the same note twice still writes the cumulative value only once.

Correct the shared bird count

The hikers agree on 10 birds. As soon as a hiker records a new sighting or correction, it is sent through the known checkpoint.

Merge rule Keep the largest sightings and corrections from each hiker.

New note In transit to a checkpoint

Shared note Being delivered to the other hikers

Alice

Agreed count received

10

Birds in this hiker's view

Bob

Agreed count received

10

Birds in this hiker's view

Carol

Agreed count received

10

Birds in this hiker's view

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

Enable JavaScript to run the demo. The starting count and expected result remain available in the article.

Run the correction race, or record new birds and corrections for any hiker.

Open the hikers' two notebook tables

Each hiker's notebook has a sightings table for the positive G-counter and a corrections table for the negative G-counter. Both tables only grow and merge by per-hiker maximum.

birds = P - N
Sightings from Alice's view Bob's view Carol's view
Agreed starting count 10 10 10
Alice 0 0 0
Bob 0 0 0
Carol 0 0 0
Corrections from Alice's view Bob's view Carol's view
Alice 0 0 0
Bob 0 0 0
Carol 0 0 0

The correction survives the merge

After both notes arrive, the positive G-counter totals 13 and the negative G-counter totals 1. Alice, Bob, and Carol all compute P - N = 13 - 1 = 12. Delivery order does not change that result, and a repeated note does not apply the correction twice.

A PN-counter can also produce a negative value. That is correct counter behavior, but it may be invalid for the thing being counted. An application that must never show fewer than zero birds needs another rule to prevent or coordinate those updates.

Sources and implementation

This lesson calls Watershed's public PN-counter kernel and sends the three hikers' notes through Sluice, Watershed's in-memory server for a collaborative document.

The merge rule follows the state-based positive-negative counter described in A comprehensive study of Convergent and Commutative Replicated Data Types.