v0.17.0
This feature release completes online shard splitting with coordinator-driven automatic splits, introduces dynamic cluster administration (data-server and namespace CRUD through the admin API and CLI), and adds coordinator high availability with leader election and admin-request redirection. It also brings major performance, durability, and stability improvements across the WAL, replication, session, and read paths.
Compatibility
- Upgrade coordinators before data servers. v0.17.0 introduces a coordinator-to-data-server instance-ID handshake that gates all internal RPCs: an upgraded coordinator manages v0.16.x data servers through a deprecated
GetInfofallback, but a v0.16.x coordinator cannot initialize v0.17.0 data servers (#1048, #1199). - Complete the data-server roll promptly. Once an upgraded data server is bound to the coordinator, it rejects internal RPCs that do not carry the instance ID, so v0.16.x leaders cannot replicate to already-upgraded followers; leadership converges onto upgraded nodes through the normal restart-driven elections. Avoid pausing the roll with a minority of data servers still on v0.16.x.
- Public RPC authority validation is enabled by default. Data servers reject client RPCs whose gRPC
:authoritydoes not match an advertised or configured address withPERMISSION_DENIED: oxia: unexpected authority, as v0.16.3 briefly did before v0.16.5 made the check opt-in. Clients connecting through proxies, load balancers, or alternate DNS names need those addresses listed in the cluster-configallowExtraAuthorities, or the check disabled withfeatureFlags.authorityValidation: falsein the data server config (#1038, #1134). - Client-facing errors now use standard gRPC status codes with Oxia error reasons attached as
ErrorInfodetails, and the unusedLeaderHintmessage was removed. Mixed-version clients and servers interoperate, but non-Go client implementations matching the old custom status codes must adapt (#1118, #1119). - The admin
ListNamespacesresponse changed from a list of names to a list ofNamespaceViewobjects carrying spec and live status, and the deprecatedListNodesRPC was removed together with theoxia admin list-nodesandoxia admin list-namespacescommands; useoxia admin dataserver getandoxia admin namespace get(#1087, #1203). - Coordinator metadata written by v0.17.0 stays readable by v0.16.3+ readers for the Kubernetes ConfigMap and Raft providers, keeping rollback possible. Status-document compatibility for the
filemetadata provider is not preserved (#1099, #1105, #1207).
Requirements
- No data migration is required on data servers.
- Coordinator config: rename
server.admintoserver.public; the CLI bind flag changed from--admin-addr/-ato--public-addr/-p, keeping the default port 6651 (#1154). - Coordinator cluster config is now sourced through the metadata provider: set
metadata.kubernetes.configNameormetadata.file.configName(withmetadata.file.dir). The--conf/-fand--cconfigflags, including theconfigmap:<namespace>/<name>form, are deprecated but still accepted and mapped onto the new settings (#1059). - Cluster config: namespace anti-affinity rules moved from
policy.antiAffinitiestoantiAffinitiesdirectly on the namespace; the old key is not read (#1101).
Public API Changes
- Admin protocol: added
CreateDataServer,PatchDataServer, andDeleteDataServer(completing the data-server registry introduced in v0.16.3) and namespace CRUD RPCs (CreateNamespace,GetNamespace,PatchNamespace,DeleteNamespace);ListDataServersandListNamespacesresponses now carry views with live status; removed the deprecatedListNodesRPC (#1087, #1091, #1092, #1093, #1094, #1095, #1096, #1097, #1129, #1203). - Coordination protocol: added the
HandshakeRPC binding data servers to their coordinator and reporting supported features (GetInfois deprecated, kept as a rolling-upgrade fallback), and theFreezeShardRPC used to quiesce a parent shard at split cutover;GetStatusnow returns per-shardShardStatswith db size and operation counters (#1048, #1197, #1202). - Replication protocol: leaders advertise
cumulative_acks_supportedonAppend, letting followers acknowledge a whole sync round with one cumulative ack; older followers keep acking per entry (#1164). - Client protocol:
NotificationBatchentries changed from a map to a wire-compatible repeated field emitted in sorted key order, making the serialized batch deterministic across replicas; existing client implementations keep working unchanged (#1190). - Cluster configuration schema: new
coordinators(name and public address per coordinator) andautoSplitsections (#1201, #1202).
Go Client Library
Relative to the last published client module version, oxia/v0.16.1:
SyncClientandAsyncClientare unchanged.- Breaking:
AdminClientwas reworked. Every method takes acontext.Context, data-server and namespace CRUD methods were added,ListNamespacesreturns[]*proto.NamespaceView, andListNodeswith its result types was removed (#1087, #1091, #1092, #1093, #1094, #1095, #1096, #1097, #1203). - Added
ErrUnauthorized,ErrUnauthenticated, andErrUnknownsentinel errors, matchable witherrors.Is(#1036).
Metrics Changes
- Added
oxia_coordinator_autosplit_evaluations_totalandoxia_coordinator_autosplit_splits_initiated_totalcounters on the coordinator (#1205). - Shard-split observer metrics on the parent leader, introduced with the split groundwork in v0.16.2 but not documented then:
oxia_server_observer_snapshots_started/_completed/_failed/_sent,oxia_server_observer_snapshots_transfer_time, and the per-observeroxia_server_observer_ack_offsetgauge for monitoring split catch-up (#945). oxia_server_session_activechanged from an asynchronous gauge to an up-down counter: the value and Prometheus exposition are unchanged, but OTLP pipelines filtering by instrument type now see a non-monotonic sum (#1182).
Operational Changes
- Automatic shard splitting is available and disabled by default: when
autoSplitis enabled in the cluster config, the coordinator initiates splits from sustained per-shard size/throughput stats, with stabilization and cooldown windows and a max-shards-per-namespace guard (#1202, #1205). - Multiple coordinators can run against shared metadata: each coordinator has a stable identity (
metadata.name, defaulting to the hostname), the elected leader publishes its address in the metadata lease, and admin requests reaching a non-leader are redirected to the leader; coordinator public addresses are listed in the cluster config (#1155, #1156, #1192, #1201). - The admin CLI was restructured into resource command groups:
oxia admin namespace create|get|patch|delete,oxia admin dataserver create|get|patch|delete, andoxia admin shard split(replacingsplit-shard), with a new-o/--output json|yaml|tableselector; admin and client CLIs accept--auth-token/--auth-token-fileindependently of TLS (#1057, #1104, #1109, #1114). - Empty cluster configs are accepted, so a cluster can be bootstrapped and then populated entirely through the admin API (#1079).
- Node saturation no longer triggers leader elections: a server that misses health probes only because it is overloaded no longer causes re-election storms that amplify the overload (#1233).
- Sessions scale much further: per-session expiry goroutines were replaced by a shared scheduler, cutting per-session overhead from kilobytes plus a goroutine to about a hundred bytes (#1236).
- The coordinator exits on metadata leadership loss instead of risking a split brain (#1175).
- Log noise reduced during startup, elections, and client disconnects; session lifecycle logging moved to debug level (#1208, #1212, #1213, #1226, #1229).
--profilenow also enables mutex and block profiling (#1238).
Changes Since v0.16.3
Fixes that were backported to the v0.16.4-v0.16.7 patch releases are also included below, since v0.17.0 supersedes the release-0.16 branch (#1115, #1116, #1123, #1124, #1133, #1134, #1137, #1139, #1143, #1144, #1147, #1175).
- shard split: correct split cutover end to end — children fenced at the parent's term, parent frozen and drained before fencing, namespace term options carried to children, and commit offsets propagated to observers parked at the WAL head (#1173, #1197, #1224, #1232)
- coordinator: automatic shard splitting driven by per-shard stats (#1202, #1205)
- coordinator: admin CRUD APIs and CLI for data servers and namespaces, with status views and output formats; deprecated ListNodes removed (#1057, #1087, #1091, #1092, #1093, #1094, #1095, #1096, #1097, #1129, #1203)
- coordinator: leader election with stable identities, lease-published public addresses, and admin-request redirection to the leader (#1155, #1156, #1192, #1201)
- coordinator: instance-ID handshake binding data servers to the coordinator, with initial elections gated on the handshake (#1048, #1199)
- coordinator: config model cleanup —
server.publicrename, cluster config sourced through the metadata provider, empty cluster configs accepted, namespace anti-affinities directly on the namespace (#1154, #1059, #1079, #1101) - coordinator: metadata schema normalized to protobuf while keeping YAML/JSON documents compatible with v0.16.3+ readers (#1099, #1105, #1207)
- coordinator: prevent node saturation from triggering leader elections (#1233)
- coordinator: raft metadata provider hardening — snapshot retention, resource lifecycle, FSM synchronization, and exit on leadership loss (#1170, #1172, #1175)
- coordinator: require synced status before balancing, avoid blocking best-effort election enqueue, synchronize runtime close with shard deletion (#1106, #1222, #1241)
- wal: recover segments with empty or stale index files instead of panicking, reject empty index files, close read-only files on mmap errors (#1228, #1230, #1231)
- wal: make rolled-over segments durable before acknowledging them, and fix a self-deadlock when truncating below all retained segments (#1176, #1178)
- wal: stop blocking appends and reads during fsync, defer segment fsync out of the rollover path, marshal entries into reusable buffers (#1160, #1161, #1162)
- replication: reject gapped appends instead of acking entries the follower does not have (#1239)
- replication: coalesce follower acks into one cumulative ack per sync round, run commit callbacks off the quorum-ack tracker lock, send duplicate-entry acks from the syncer goroutine (#1164, #1159, #1177)
- replication: keep snapshot-bootstrapped followers eligible for leader election, drain follower cursors on close (#1163, #1139)
- dataserver: prevent a slow WriteStream client from stalling the whole shard (#1158)
- dataserver: persist control-request commit offsets and enabled features across restarts (#1133, #1137)
- dataserver: drain leader operations before closing the Pebble DB, avoid killing the process when Close() races gRPC Serve() (#1143, #1169)
- dataserver: use the Pebble default memtable size instead of a fixed 32 MiB per shard (#1123)
- dataserver: skip unchanged periodic shard-status persists, allocation-free condition broadcasts, skip debug-log attribute boxing when the level is off (#1183, #1185, #1186)
- database: run reads, lists and range scans inline on the handler goroutine, decode each scanned key once, marshal new entries directly into the Pebble batch arena, skip copying old values when only metadata is needed (#1191, #1184, #1189, #1188)
- database: seek past the internal-key region instead of stepping through it, drop a duplicated seek in getHigher, avoid decoding internal keys in place (#1243, #1242, #1181)
- sessions: replace per-session goroutines with a shared session-expiry scheduler (#1236); close sessions outside the session-manager lock and avoid re-acquiring it on failed session starts (#1171, #1179)
- notifications: retry stream initialization on retryable errors, stop dispatcher failures from becoming permanent, initialize dispatch from the notification offset, enforce the read batch limit, make batch serialization deterministic (#1165, #1144, #1147, #1187, #1190)
- client: standardize on gRPC error codes with Oxia error details (#1118, #1119)
- client: fix stuck shard-assignment streams by draining server-side termination signals (#1215, #1216); discard multi-shard get responses after the first error (#1180)
- client/dataserver: refresh stale pooled gRPC connections and align eviction with keepalive (#1115, #1116)
- security: enable public RPC authority validation by default, strip schemes from configured authorities (#1134, #1124)
- cli: auth token flags decoupled from TLS (#1109, #1114); mutex and block profiling with
--profile(#1238) - logging: quieter startup, elections, and disconnects; session lifecycle logs at debug level; deduplicated JSON
timefield and human-readable durations (#1075, #1076, #1208, #1212, #1213, #1226, #1229) - deps: grpc-go 1.81.1 with CodecV2 registration (#1167, #1168); golang.org/x/net v0.55.0 fixing multiple HIGH CVEs (#1200); golang.org/x/crypto 0.52.0 (#1220)
Full Changelog: v0.16.3...v0.17.0