Consensus Model

Oak Chain's consensus boundary sits between signed write intent and persisted Oak segment store. Every accepted write crosses this boundary; nothing else in the architecture replays the same log. Aeron Cluster (Raft over Aeron's UDP messaging) was chosen because the boundary has to be cheap enough to live in the AEM write path without dominating tail latency, and deterministic enough that mounted downstream Oak instances can trust the output without re-validating it.

The whole stack operates below JCR. Validators produce segments, not nodes; AEM-the-application sees normal Oak content through the mount, exactly as it would over any other NodeStore. Cryptographic provenance (Raft term, commit index, validator signature, on-chain settlement reference) is segment-resident, surfaced for operators through oak-segment-consensus tooling and the validator's own observability routes, not as JCR properties.

The route hierarchy below distinguishes source truth (/v1/consensus/*, /v1/ops/snapshots/*) from local diagnosis (/v1/aeron/*) from edge-composed upstream (/ops/v1/*). Read the role and write-path diagrams first, then query source routes before reaching for local diagnostic or upstream views.

Contract Boundary

Consensus truth starts at the validator-native source routes.

Use /v1/consensus/leader and /v1/consensus/status for normalized leader and role state.

Use /v1/ops/snapshots/{cluster,queue,replication,runtime} for governed consensus-adjacent observability.

Treat /v1/aeron/* and /health/deep as local diagnostic detail.

Treat /ops/v1/* as the edge-owned remote contract built from source routes, not as a second consensus engine.

Why Aeron?

Data Table
Requirement
Aeron Solution
Low latency
UDP and shared-memory messaging
Deterministic
Replay-based state machine
Proven
Used in production at scale
Failover
Automatic leader election

Low-latency messaging. Aeron sends messages over UDP through a user-space media driver, and over shared memory between processes on the same host. It was designed for low, predictable latency, which is why it was chosen for the write path.

Replay-based state machine. Aeron Cluster commits an ordered log; followers don't receive cluster state, they receive cluster commands and execute them in identical order. The output is therefore deterministic by construction: given the same log, every validator ends with the same content (the same nodes, property types and values). Convergence is logical. Physical details such as RecordIds, journal heads and TAR files may differ between validators. This is what makes any validator a trustworthy mount source.

Proven at scale. Aeron came out of Real Logic's work in financial trading systems, where the failure mode for non-determinism is "your trade settles at a different price than your counterparty thinks." The same property (ordered, replicated, replayable command log) is what makes it appropriate for content authorization, where the failure mode is "your AEM author's signed write produces inconsistent committed state across the cluster."

Automatic failover. If the leader fails, the remaining validators elect a new one. New writes cannot commit until they do. Timing and its limits are under Leader Election.

How It Works

Roles

graph LR
    L[Leader] -->|Replicates| F1[Follower 1]
    L -->|Replicates| F2[Follower 2]
    C[Client] -->|Writes| L
    C -.->|Redirected| F1
    C -.->|Redirected| F2

Write Path

sequenceDiagram
    participant C as Client
    participant L as Leader
    participant F as Followers

    C->>L: POST /v1/propose-write
    L->>L: Check signature, queue
    L-->>C: 202 PENDING
    L->>L: Verify payment (mock: simulated)
    L->>F: Ordered command (Aeron)
    L->>L: Apply to own store
    F->>F: Apply to own store
    Note over L,F: COMMITTED after majority apply and flush
    C->>L: GET /v1/ops/operations/{id}
    L-->>C: Final state

The final state is COMMITTED, FAILED or TIMED_OUT.

Leader Election

When the leader fails:

  1. Followers detect missing leader heartbeats.
  2. One follower becomes candidate.
  3. The candidate requests votes from peers.
  4. A majority vote elects the new leader.
  5. Source routes converge on the new leader, and the edge contract follows them.

Failover time: the validator uses Aeron's default timers. The leader sends a heartbeat every 200 ms. Followers treat the leader as lost after 10 s without one (leader heartbeat timeout), then elect a new leader. Each voting round waits up to 1 s (election timeout). There is no measured failover target, and crash and restart recovery is not yet validated.

Deterministic State Machine

All validators execute the same operations in the same order.

public void onSessionMessage(ClientSession session,
                             long timestamp,
                             DirectBuffer buffer) {
    WriteProposal proposal = decode(buffer);
    nodeStore.merge(proposal.path, proposal.content);
}

Given the same replicated log, validators converge on the same repository content. Their physical segment files may differ.

How Consensus Reaches Existing AEM Repositories

Validators don't extend JCR. They live below it. The cluster's job ends at producing a consensus-validated Oak segment store. That store is then mounted into existing AEM repositories via Apache Jackrabbit Oak's CompositeNodeStore at the NodeStore layer. Validators serve their segment files over HTTP (/segments/, /journal.log, /manifest), and the read-only mount in AEM 6.5 LTS reads them with the Oak Chain Connector's mount bundle (federated validator clusters use the consensus/mount/http package in oak-segment-consensus).

graph TB
    subgraph aem[Existing AEM]
      sling[Sling / JCR API]
      composite[CompositeNodeStore]
      local[Local Oak NodeStore]
    end
    subgraph cluster[Validator Cluster]
      raft[Aeron Cluster - Raft]
      seg[Consensus-validated Oak segment store]
    end
    sling --> composite
    composite -->|standard paths| local
    composite -->|mounted subtree| seg
    raft -->|commits| seg

Inside AEM the mounted content is ordinary JCR, read by path: Sling resolves resources and the JCR API returns nodes. Oak's indexes do not cover the mount, and chain changes reach JCR observation with AEM's next commit. The cryptographic guarantees live one layer below, in segment metadata, surfaced for operators through oak-segment-consensus tooling and the validator's source-truth routes.

This is the integration model: an existing AEM 6.5 LTS author adopts Oak Chain by mounting a subtree read-only, with no application code change and full segment-level provenance available to operators. It is demonstrated on AEM 6.5 LTS SP3 (see AEM 6.5 LTS Integration); cross-cluster deployments are not yet validated.

Observation Order

1. Source Truth

Use these first when you need authoritative consensus state from the validator.

curl -s http://127.0.0.1:8090/v1/consensus/leader | jq .
curl -s http://127.0.0.1:8090/v1/consensus/status | jq .
curl -s http://127.0.0.1:8090/v1/ops/snapshots/cluster | jq .
curl -s http://127.0.0.1:8090/v1/ops/snapshots/queue | jq .
curl -s http://127.0.0.1:8090/v1/ops/snapshots/replication | jq .

2. Local Diagnosis

Use these only when the normalized source routes are not enough.

curl -s http://127.0.0.1:8090/v1/aeron/cluster-state | jq .
curl -s http://127.0.0.1:8090/v1/aeron/raft-metrics | jq .
curl -s http://127.0.0.1:8090/v1/aeron/node-status?nodeId=0 | jq .
curl -s http://127.0.0.1:8090/v1/aeron/replication-lag | jq .

3. Canonical Upstream

Use these for remote dashboards, operators, and product-facing read models.

curl -s http://127.0.0.1:8787/ops/v1/cluster | jq .
curl -s http://127.0.0.1:8787/ops/v1/queue | jq .
curl -s http://127.0.0.1:8787/ops/v1/replication | jq .
curl -s http://127.0.0.1:8787/ops/v1/durability | jq .
curl -s http://127.0.0.1:8787/ops/v1/finality | jq .

Configuration

Cluster Members

Set membership with -D system properties on each validator. For a local three-validator cluster, oak-chain mock up from oak-chain-infra starts all three.

-Daeron.cluster.nodeId=0                              # this validator's index
-Daeron.cluster.hostnames=localhost,localhost,localhost  # one host per member
-Daeron.cluster.basePort=9000                         # Aeron UDP ports: basePort + 100 x nodeId + 1 to 7

Timeouts

Data Table
Parameter
Default
Description
aeron.cluster.leader.heartbeat.interval
200 ms
Leader heartbeat frequency
aeron.cluster.leader.heartbeat.timeout
10 s
Time without a heartbeat before followers start an election
aeron.cluster.election.timeout
1 s
How long a voting round waits before it retries
oak.cluster.session.timeout.seconds
30 s
Client session timeout

The first three are Aeron defaults; the validator does not change them.

Failure Scenarios

These steps describe the Raft design. Crash and restart recovery, quorum loss and partitions are not yet validated.

Leader Failure

  1. Followers detect timeout.
  2. Election occurs.
  3. A new leader is elected.
  4. Source routes converge, and the edge contract follows the new leader.

Follower Failure

  1. The leader continues with the remaining quorum.
  2. The failed follower rejoins via snapshot and replay.
  3. Local diagnostic routes can show lag during catch-up, but source snapshots stay the primary contract.

Network Partition

  1. The minority partition cannot elect a leader.
  2. The majority partition continues.
  3. The minority rejects writes because quorum is unavailable.
  4. Source routes and edge composition recover once the partition heals.

Monitoring

Use /v1/consensus/leader for normalized leader lookup.

Use /v1/ops/snapshots/runtime for governed runtime state.

Use /v1/aeron/* only when you need raw local diagnostic detail.

curl -s http://localhost:8090/v1/consensus/leader | jq .
curl -s http://localhost:8090/v1/ops/snapshots/runtime | jq .
curl -s http://localhost:8090/v1/ops/snapshots/queue | jq .

Prometheus Metrics

Data Table
Metric
Description
oak_consensus_is_leader
1 on the leader, 0 on followers
oak_consensus_leader_epoch
Increments on each leader change
oak_consensus_time_since_last_heartbeat_seconds
Seconds since the last leader heartbeat
oak_validators_reachable
Validators answering health checks

Next Steps