How Aeron Cache fits together — a stateless gateway tier and its transports in front of a
RAFT consensus core — and how that same core deploys as three shapes. Click the pieces to explore.
01
Anatomy: stateless gateways over a consensus core
Clients
↓→
Edge
↓→
Stateless gateway tier · scale freely
↓→cluster session
Consensus core · fixed
writes → leader · commit on quorum
The two-tier split
Aeron Cache divides into a stateless gateway tier you scale out freely, and a fixed consensus core sized once for fault tolerance. Every gateway is itself an Aeron Cluster client holding one session to the elected leader, multiplexing many end-clients over it. Click any component to see its role.
Web console
Client
The Next.js console bundled with the all-in-one install — browse caches, write items, set TTLs, inspect JSON values and counters, and trigger snapshots. Connects over HTTP + WebSocket.
Rust CLI (ac-cli)
Client
Drives the full cache and counter surface straight over the REST API — scriptable and CI-friendly. brew install aeron-cache-cli.
Embedded clients
Client
Polyglot clients for Java, TypeScript, Python and Rust that wrap every interface and keep a live local mirror over the stream — network-free reads with no tier to operate.
Load balancer
Edge
Spreads clients across interchangeable gateway replicas. Keep WebSocket/SSE on connection-aware balancing so long-lived streams are not torn mid-flight, and gate replica readiness on a live cluster session, not just an open port.
HTTP REST gateway
Gateway · :7070
Stateless request/response over JSON under /api/v1, served by Javalin and always on. Every response carries an operationStatus rather than leaning on HTTP codes. The easy scaling case — round-robin L7, bound by CPU / request-rate. Optional near cache (NEAR_CACHE_ENABLED): reads on the same GET URIs are served from a warm local copy kept live by a cluster subscription — no client change.
WebSocket gateway
Gateway · :7071
Subscribe routes push server→client; the /api/ws/v1/bidi socket carries the full command + subscription surface both ways, each frame correlated by id. Long-lived connections — autoscale on open-connection count, not CPU. WEBSOCKET_GATEWAY_ENABLED (default on). With NEAR_CACHE_ENABLED, hydrating subscriptions (including over the bidi socket) are served their snapshot from a warm near cache instead of a per-subscriber cluster fetch.
SSE gateway
Gateway · :7072
Server→client only, text/event-stream — the browser-native way to receive live CacheUpdateEvent frames. Bound by concurrent connections like WebSocket. SSE_GATEWAY_ENABLED (default on). With NEAR_CACHE_ENABLED, hydrating subscriptions are served their snapshot from a warm near cache instead of a per-subscriber cluster fetch.
Aeron SBE gateway
Gateway · UDP :7075/76 or IPC
Binary, zero-copy, bidirectional over Aeron (SBE schema id 7) for JVM & Rust clients. Scales by placement, not a load balancer: UDP uses Aeron channel addressing; IPC co-locates the gateway with its clients (sidecar / per-host). AERON_GATEWAY_ENABLED (default off). With NEAR_CACHE_ENABLED, hydrating subscriptions are served from a warm near cache here too.
RAFT leader
Core
The single elected node that sequences every write. A mutation commits once a majority (quorum) has persisted it — exactly what makes failover linearizable. Writes funnel here: the core is a consistency tier, not a throughput knob.
Followers (×2)
Core
Replicate the leader’s log and stand ready to take over on leader loss. A 3-node cluster tolerates the loss of one (majority = 2). More nodes buy fault tolerance, not write throughput — every write still funnels through one leader.
Replicated log + snapshots
Core
The durable state, on a per-node PVC. Recovery loads the latest snapshot and replays only the tail after it. Even TTL is a committed, replayable timer event — determinism is what keeps every replica in agreement.
Scaling splits cleanly: the gateways are Deployments you grow per-interface, the core is a
StatefulSet sized once for your failure budget. More on
scaling the gateways →
02
Three deployment shapes, one ClusteredService
The same deterministic service runs in three topologies — the trade-off is purely operational.
Develop against ephemeral or the all-in-one install, deploy to the 3-node cluster; the business logic is identical.
Gateway Deployments ×N
HTTP · WS · SSE · Aeron
↓ cluster sessions
RAFT core · StatefulSet
Leader
Follower
Follower
log + snapshots on PVCs · commit on quorum
Clustered
Full RAFT · highly available
A Kubernetes StatefulSet of 3 replicas running the full RAFT cluster, with the stateless gateways as separate Deployments in front. Survives node loss with no acknowledged-write loss.
Topology
3-node core + scalable gateway tier
Availability
Tolerates loss of 1 node (quorum = 2)
Durability
Replicated log + snapshots on PVCs
Best for
State that must outlive a pod
Launch
make all · Helm (CACHE_MODE=RAFT)
Gateways
HTTP · WS · SSE · Aeron
↓
Single non-RAFT node
no quorum · no replication · in-memory
Ephemeral
Single node · no consensus
EphemeralCacheApplication — one non-RAFT node. No quorum, no replication, lower overhead. The cache is lost on restart, by design.
over IPC a co-located JVM / Rust client reaches the whole stack zero-copy, no network hop
All-in-one
One process · the whole stack
cache-monolith launches a single-node cluster plus the HTTP, WebSocket and SSE gateways in one process, and the Homebrew and Helm packages add the web UI — the full API surface, zero cluster ceremony. It also embeds the Aeron SBE gateway: enable it over IPC (AERON_GATEWAY_ENABLED=true, GATEWAY_TRANSPORT_MEDIA=ipc) and a co-located JVM or Rust client reaches the whole stack over shared memory — zero-copy, no kernel network path — all on one host.
Topology
Core + all gateways + UI, one process
Fast path
Embedded Aeron SBE over IPC (opt-in)
Availability
Single process (local)
Durability
Single-node cluster
Best for
Local desktop & first-run
Launch
brew install aeron-cache
The determinism that makes the single node correct is exactly what makes the cluster consistent —
RAFT consensus →
03
Four transports, one cache
The same key-value and counter model is exposed over four interfaces that share one command
vocabulary — they differ only in framing, directionality, and how far down the latency curve
they reach. Select one to compare.
Client
app · browser · service
→
HTTP REST
:7070 · /api/v1
→
Core
RAFT cluster
Port / path
:7070 · /api/v1
Direction
Request → response
Streaming
No
Format
JSON
Flag
Always on
When: CRUD, scripting, tooling — anything that just needs request/response.
Client
app · browser · service
→
WebSocket
:7071 · /api/ws/v1/…
→
Core
RAFT cluster
Port / path
:7071 · /api/ws/v1/…
Direction
Server→client, or bidirectional
Streaming
Yes
Format
JSON
Flag
WEBSOCKET_GATEWAY_ENABLED (true)
When: Receiving updates in a service — or the full command + subscription surface over one socket (bidi).
Client
app · browser · service
→
SSE
:7072 · /api/sse/v1/…
→
Core
RAFT cluster
Port / path
:7072 · /api/sse/v1/…
Direction
Server → client only
Streaming
Yes
Format
text/event-stream
Flag
SSE_GATEWAY_ENABLED (true)
When: Receive-only live updates in a browser, with no client library.
Client
app · browser · service
→
Aeron SBE
UDP :7075/:7076 or IPC
→
Core
RAFT cluster
Port / path
UDP :7075/:7076 or IPC
Direction
Bidirectional
Streaming
Yes
Format
SBE binary (schema id 7)
Flag
AERON_GATEWAY_ENABLED (false)
When: Latency-sensitive JVM or Rust clients — binary, zero-copy, over Aeron UDP or IPC.
Decision shortcut —
CRUD or tooling → HTTP. Receive-only in a browser → SSE. Receive-only in a service → uni WebSocket.
Commands and subscriptions over one socket → bidi WebSocket. Lowest latency on the JVM or in Rust → Aeron SBE.
Full detail in the API overview →