Clustering
Operations API for managing Harper's replication system. For an overview of how replication works, see Replication Overview. For sharding configuration, see Sharding.
All clustering operations require super_user role.
Add Node
Adds a new Harper instance to the cluster. If subscriptions are provided, it creates the specified replication relationships between the nodes. Without subscriptions, a fully replicating system is created (all data in all databases).
Parameters:
operation(required) — must beadd_nodehostnameorurl(required) — the hostname or URL of the node to addverify_tls(optional) — whether to verify the TLS certificate. Set tofalsetemporarily on fresh installs with self-signed certificates. Defaults totrueauthorization(optional) — credentials for the node being added. Either an object withusernameandpassword, or an HTTPAuthorizationstyle stringretain_authorization(optional) — iftrue, stores credentials and uses them on every reconnect. Generally not recommended; prefer certificate-based authentication. Defaults tofalserevoked_certificates(optional) — array of revoked certificate serial numbers that will not be accepted for any connectionsshard(optional) — shard number for this node. Only needed when using shardingstart_time(optional) — ISO 8601 UTC datetime. If set, only data after this time is downloaded during initial synchronization instead of the entire databasesubscriptions(optional) — explicit table-level replication relationships. This is optional (and discouraged). Each subscription is an object with:database— database nametable— table namesubscribe— iftrue, transactions on the remote table are replicated locallypublish— iftrue, transactions on the local table are replicated to the remote node
Request:
{
"operation": "add_node",
"hostname": "server-two",
"verify_tls": false,
"authorization": {
"username": "admin",
"password": "password"
}
}
Response:
{
"message": "Successfully added 'server-two' to cluster"
}
Note:
set_nodeis an alias foradd_node.
Update Node
Modifies an existing Harper instance in the cluster. Will attempt to add the node if it does not exist.
Parameters:
operation(required) — must beupdate_nodehostname(required) — hostname of the remote node to updaterevoked_certificates(optional) — array of revoked certificate serial numbersshard(optional) — shard number to assign to this nodesubscriptions(required) — array of subscription objects (same structure asadd_node)
Request:
{
"operation": "update_node",
"hostname": "server-two"
}
Response:
{
"message": "Successfully updated 'server-two'"
}
Remove Node
Removes a Harper node from the cluster and stops all replication to and from that node.
Parameters:
operation(required) — must beremove_nodehostname(required) — hostname of the node to remove
Request:
{
"operation": "remove_node",
"hostname": "server-two"
}
Response:
{
"message": "Successfully removed 'server-two' from cluster"
}
Cluster Status
Returns an array of status objects from the cluster, including active WebSocket connections and replication timing statistics.
Added in: v4.4.0 ; timing statistics added in v4.5.0
Parameters:
operation(required) — must becluster_status
Request:
{
"operation": "cluster_status"
}
Response:
{
"type": "cluster-status",
"connections": [
{
"replicateByDefault": true,
"replicates": true,
"url": "wss://server-2.domain.com:9933",
"name": "server-2.domain.com",
"subscriptions": null,
"database_sockets": [
{
"database": "data",
"connected": true,
"latency": 0.7,
"thread_id": 1,
"nodes": ["server-2.domain.com"],
"lastCommitConfirmed": "Wed, 12 Feb 2025 19:09:34 GMT",
"lastReceivedRemoteTime": "Wed, 12 Feb 2025 16:49:29 GMT",
"lastReceivedLocalTime": "Wed, 12 Feb 2025 16:50:59 GMT",
"lastSendTime": "Wed, 12 Feb 2025 16:50:59 GMT"
}
]
}
],
"node_name": "server-1.domain.com",
"is_enabled": true
}
database_sockets shows the actual WebSocket connections between nodes — one socket per database per node. Timing fields:
| Field | Description |
|---|---|
lastCommitConfirmed | Last time a receipt of confirmation was received for an outgoing commit |
lastReceivedRemoteTime | Timestamp (from the originating node) of the last received transaction |
lastReceivedLocalTime | Local time when the last transaction was received. A gap between this and lastReceivedRemoteTime suggests the node is catching up |
sendingMessage | Timestamp of the transaction actively being sent. Absent when waiting for the next transaction |
Configure Cluster
Bulk creates or resets subscriptions for any number of remote nodes. Resets and replaces any existing clustering setup.
Parameters:
operation(required) — must beconfigure_clusterconnections(required) — array of node objects following theadd_nodeschema
Request:
{
"operation": "configure_cluster",
"connections": [
{
"hostname": "server-two",
"verify_tls": false,
"authorization": {
"username": "admin",
"password": "password2"
}
},
{
"hostname": "server-three",
"verify_tls": false,
"authorization": {
"username": "admin",
"password": "password3"
}
}
]
}
Response:
{
"message": "Cluster successfully configured."
}
Cluster Set Routes
Adds routes to the replication.routes configuration. Behaves as a PATCH/upsert — adds new routes while leaving existing routes untouched.
Parameters:
operation(required) — must becluster_set_routesroutes(required) — array of route strings (wss://host:port) or objects withhostnameandportproperties
Request:
{
"operation": "cluster_set_routes",
"routes": [
"wss://server-two:9925",
{
"hostname": "server-three",
"port": 9930
}
]
}
Response:
{
"message": "cluster routes successfully set",
"set": ["wss://server-two:9925", { "hostname": "server-three", "port": 9930 }],
"skipped": []
}
Cluster Get Routes
Returns the replication routes from the Harper config file.
Parameters:
operation(required) — must becluster_get_routes
Request:
{
"operation": "cluster_get_routes"
}
Response:
["wss://server-two:9925", { "hostname": "server-three", "port": 9930 }]
Cluster Delete Routes
Removes routes from the Harper config file.
Parameters:
operation(required) — must becluster_delete_routesroutes(required) — array of route objects to remove
Request:
{
"operation": "cluster_delete_routes",
"routes": [
{
"hostname": "server-three",
"port": 9930
}
]
}
Response:
{
"message": "cluster routes successfully deleted",
"deleted": [{ "hostname": "server-three", "port": 9930 }],
"skipped": []
}