etcd v3.7 adds a streaming range API and drops the legacy v2 store
Maya Okonkwo
SIG etcd cut v3.7.0 this week, and for teams operating Kubernetes the operational headline is a new streaming range API that stops the server buffering the whole result set before it answers. The release, announced on the Kubernetes blog by the maintainers, adds RangeStream to the gRPC surface and to etcdctl, tightens lease behaviour when the cluster is under load, and finally removes the legacy v2 store that etcd has been carrying since the v3 migration.
Chunked reads instead of a buffered response
The old shape of a Range call was expensive on a large keyspace. The server read every matching key/value into memory, serialized the response, then answered. Under memory pressure or a slow client the whole response sat on the server heap. RangeStream chunks that response instead. Per the release notes it is available on both the gRPC API and via etcdctl. The maintainers describe the payoff two ways: lower latency for callers reading big ranges, and more predictable memory use on both server and client. Kubernetes plans to expose it in v1.37 behind an EtcdRangeStream feature gate; until then, no default cluster behaviour changes.
Smaller wins that add up on the pager
A related optimisation lands the same release. When a Range sets keys_only (or an operator runs etcdctl get --keys-only), etcd will read solely from the in-memory index, skipping the bbolt load of serialized values entirely. The one exception the release notes call out is SortTarget=VALUE, which still needs the values. For anything scanning a wide keyspace to check what exists, the backend read goes away.
Leases got two changes worth carrying into a runbook. LeaseRevoke requests are prioritised, per the notes, so leases expire on time when etcd is under load. A FastLeaseKeepAlive path renews a lease without waiting for the applied index. Both are the sort of change you notice at 3am, when a node still reporting itself alive is really a lease that a controller has been trying to revoke, and the queue in front of the revoke is what is holding the loop open. A separate find() performance change is aimed at concurrent watches over the same keys.
The bit that matters on upgrade
The removal that jumps out is the v2 store. etcd v3.7.0 boots entirely from v3store; the legacy v2 store, kept around for a long migration tail, is gone. Any tooling, health check or backup path that still leans on the v2 API surface has to move before the upgrade, not during. The release also carries a protobuf overhaul, with the old libraries replaced by supported ones, and pins bbolt at v1.5.0 and raft at v3.7.0.
What has not changed
None of this touches the consensus model. etcd is still Raft; the cluster still needs a quorum to write; the familiar failure modes for an on-call, quorum loss on member churn, snapshot restore under time pressure, watch storms after a leader change, are the same failure modes on v3.7. What the release changes is the shape of the reads and the sharpness of the lease timing. On a healthy cluster you may not notice. On the cluster where a controller decides at 2am to enumerate every pod in every namespace, the difference between chunked and buffered is the difference between backpressure and OOM.
For CI/CD teams the practical read is upstream of the pipeline. Kubernetes v1.37 is the version where the RangeStream benefit reaches the API server, and only if the feature gate is on. Everything else in v3.7 lands the day the cluster runs the new binary.
Source: Kubernetes Blog (kubernetes.io)