base-ha

command module
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 17, 2026 License: MIT Imports: 26 Imported by: 0

README

base-ha

Highly available Hanzo Base cluster.

Quasar consensus is leaderless — all nodes are equal validators. SQLite's single-writer constraint is satisfied by deterministic writer-pinning: the lowest-sorted alive NodeID holds the write lock. All others are replicas that 307 mutating requests to the writer and apply change-sets via async replication.

  • Writes (POST/PUT/PATCH/DELETE) reverse-proxy to the pinned writer.
  • Reads (GET) honor txseq cookies for read-your-writes consistency.
  • Replication is async; conflict resolution is last-writer-wins by default.
  • One binary. Single BASE_* env namespace.

Quick start

go install github.com/hanzoai/base-ha@latest

# node 1 (bootstrap)
BASE_NODE_ID=node1 \
BASE_LOCAL_TARGET=http://127.0.0.1:8090 \
BASE_PEERS=http://127.0.0.1:8091,http://127.0.0.1:8092 \
BASE_CONSENSUS=quasar \
BASE_SUPERUSER_EMAIL=admin@example.com \
BASE_SUPERUSER_PASS=change-me \
  base-ha serve --http 127.0.0.1:8090

# node 2
BASE_NODE_ID=node2 \
BASE_LOCAL_TARGET=http://127.0.0.1:8091 \
BASE_PEERS=http://127.0.0.1:8090,http://127.0.0.1:8092 \
BASE_CONSENSUS=quasar \
  base-ha serve --http 127.0.0.1:8091

Or use Docker:

docker compose up

Configuration

Cluster identity
Var Description Default
BASE_NODE_ID Unique node identifier. $HOSTNAME
BASE_LOCAL_TARGET This node's reachable URL.
BASE_PEERS CSV of peer base URLs.
Writer election
Var Values Description
BASE_CONSENSUS quasar (default), pubsub quasar is the native heartbeat writer-pin. pubsub falls back to go-ha's graft dynamic election.
BASE_STATIC_WRITER URL All nodes forward writes to this URL. Overrides election.
Replication transport
Var Description
BASE_PUBSUB_URL External broker URL (nats://pubsub:4222). Works with nats-server or hanzoai/pubsub.
BASE_PUBSUB_PORT Embedded broker port (enables embedded mode).
BASE_PUBSUB_STORE_DIR Embedded broker storage dir.
BASE_PUBSUB_CONFIG Broker config file (overrides other pubsub settings).
BASE_REPLICATION_STREAM Stream name. Default: base.
BASE_REPLICAS JetStream replica count. Default: 1.
BASE_ASYNC_PUBLISHER Enable async publish with outbox. Recommended with external broker.
BASE_ASYNC_PUBLISHER_DIR Outbox directory.
BASE_ROW_IDENTIFY pk (default), rowid, or full.
Bootstrap
Var Description
BASE_SUPERUSER_EMAIL Superuser email at startup.
BASE_SUPERUSER_PASS Superuser password at startup.

Architecture

user
 │
 ▼
[replica]  POST/PUT/PATCH/DELETE → 307 → [writer]
[replica]  GET + txseq cookie           [writer or replica with fresh state]
                                             │
                                             │ SQLite change-set replication
                                             ▼
                                         [replicas]

Writer election (BASE_CONSENSUS=quasar, default):

  • Each node heartbeats to peers every 500ms via /_ha/heartbeat.
  • Alive peers ranked by NodeID (lexicographic). Lowest = writer.
  • Lease timeout = 3 × heartbeat (1.5s).
  • No RAFT log, no snapshots. All nodes are equal validators.

Fallback (BASE_CONSENSUS=pubsub):

  • Delegates to go-ha's graft-over-JetStream election.
  • Use when you already run a NATS/pubsub cluster.

Event hooks on replicas

Replicas fire these events on replicated changes:

  • OnModelAfterCreateSuccess, OnModelAfterCreateError
  • OnModelAfterUpdateSuccess, OnModelAfterUpdateError
  • OnModelAfterDeleteSuccess, OnModelAfterDeleteError

Before* hooks fire only on the writer.

Using Hanzo pubsub as the broker

hanzoai/pubsub is wire-compatible with NATS:

docker run --rm -p 4222:4222 ghcr.io/hanzoai/pubsub:latest -js -sd /data

BASE_PUBSUB_URL=nats://localhost:4222 base-ha serve --http :8090

License

MIT.

Documentation

Overview

base-ha launches a Hanzo Base cluster with writer/replica replication.

Writer-pin uses a Quasar-derived heartbeat-lease protocol — faster and lighter than RAFT. All nodes are equal validators; the lowest-sorted alive NodeID holds the SQLite write lock. Heartbeats travel over ZAP (sub-ms binary protocol) with HTTP fallback.

All configuration lives under the BASE_* env namespace.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL