5 hours ago
zuul

v3.6.10

What's Changed

New Contributors

Full Changelog: https://github.com/Netflix/zuul/compare/v3.6.9...v3.6.10

14 hours ago
questdb

9.4.1

QuestDB 9.4.1

QuestDB 9.4.1 is a hardening release that builds on 9.4.0. A new randomized SQL query fuzzer and a stricter, fluent test-assertion framework together flushed out and fixed more than 60 latent correctness, crash, and resource-leak bugs across the JIT filter, the Parquet read path, parallel GROUP BY / filter execution, and DECIMAL handling. The release also hardens 9.4.0's new posting / covering index and Parquet-metadata subsystems, adds the array_agg() and regr_r2() aggregates, brings window functions to DECIMAL columns, introduces transactional ingestion over QWP, and speeds up materialized-view incremental refresh by up to ~90x in deep out-of-order backfill scenarios.

For any questions or feedback, please join us on Slack or on Discourse.

See also our prettier release notes page.

Highlights

Correctness hardening: a query fuzzer and stricter test assertions

Two pieces of test infrastructure that landed this cycle did most of the work in this release.

  • A new randomized query fuzzer (QueryFuzzTest) generates WAL tables across a wide range of column types and storage shapes (native, all-Parquet, mixed), then runs thousands of randomly generated queries against them. It runs each query four ways — JIT on/off, native vs. Parquet shadow table, serial vs. parallel, literal vs. bind-variable — and fails on any divergence or any internal error. It surfaced and fixed 55 distinct bugs: JIT filters that disagreed with the interpreter (narrow-int overflow, NULL propagation, AVX2 multiplication clobbering NULL lanes, var-size NULL comparisons), parallel GROUP BY / filter functions that shared mutable state across worker threads (wrong results, infinite loops, the occasional SIGSEGV), Parquet reads that returned NULL or stale data, DECIMAL pushdown that pruned valid row groups, and a long tail of compile-time NPEs and native-memory leaks on error paths.
  • A new fluent QueryAssertion builder replaced thousands of looser assertSql(...) call sites with assertions that also check cursor size, random-access support, scan direction, and calculateSize() behaviour. Turning those checks on across the test tree exposed and fixed 9 more production bugs, including DOUBLE-array arithmetic (+, -, *, /) failing on the row after a NULL array, a window-join cursor-size miscount, and a row-cursor that was never freed.

The net effect is a meaningfully more correct SQL engine, especially for JIT-compiled filters, Parquet-backed queries, and highly parallel aggregations.

⚠️ Three of these correctness fixes change query results and are worth checking against your workload (see Behaviour changes below):

  • INT - FLOAT now returns FLOAT instead of DOUBLE.
  • Nested INT arithmetic compared in a LONG context (e.g. long_col <= (int_a * int_b) + int_c) now computes at 64-bit width instead of wrapping at 32-bit.
  • STRING / VARCHAR <= null and >= null now return matching NULL rows instead of zero rows, aligning the literal and bind-variable forms.

by @puzpuzpuz in #7021 and @bluestreak01 in #7187

array_agg()

A new aggregate that collects per-group values into a DOUBLE[]:

SELECT symbol, array_agg(price) FROM trades SAMPLE BY 1m;

array_agg(DOUBLE) and array_agg(DOUBLE[]) both preserve input order across keyed and non-keyed GROUP BY and SAMPLE BY, including under parallel execution, and the result feeds straight into the array functions (array_sum, array_count, indexing). NULL inputs are kept as null elements; FILL(NULL) / FILL(PREV) are supported in SAMPLE BY, while FILL(LINEAR) / FILL(VALUE) are rejected at compile time. See the aggregate functions reference and the array type. by @javier in #6812

regr_r2()

regr_r2(y, x) is the standard SQL coefficient of determination — how well a linear regression of Y on X fits, on a 0–1 scale. It is handy for separating real trends from noise, e.g. finding sensors whose temperature is genuinely trending up versus drifting randomly. The implementation also lays the groundwork for the remaining SQL-standard regression aggregates. See the aggregate functions reference. by @jovfer in #7104

Window functions for DECIMAL columns

All six DECIMAL sub-types (D8–D256) now work with the window functions first_value, last_value, nth_value, lag, lead, min, max, count, sum, and avg — across the same frame shapes (whole partition, ROWS BETWEEN, RANGE BETWEEN, partitioned and non-partitioned) supported for the primitive numeric types. sum deliberately widens its output type to avoid silent overflow on long-running aggregations. See the window functions reference and the DECIMAL type. by @kafka1991 in #7135

Transactional ingestion and wider type coverage over QWP

For users on QWP (QuestDB's WebSocket-based wire protocol) and the latest java-questdb-client:

  • Deferred commit / transactions. A new transaction=on connect-string option (and transactional(boolean) builder method) lets a logical batch span multiple wire messages and commit only on an explicit flush(). This removes the old hard coupling between http.recv.buffer.size and the maximum transaction size. Older servers degrade gracefully (each message commits independently). by @bluestreak01 in #7144
  • IPv4 ingest, GEOHASH coverage, and a batch-size handshake. QWP ingestion now accepts IPv4 columns and the full range of GEOHASH precisions, and the server advertises its effective payload cap in an X-QWP-Max-Batch-Size header on the upgrade response so clients no longer have to discover it by overflowing. by @bluestreak01 in #7108

Posting and covering index hardening

9.4.0 introduced the posting / covering index for SYMBOL columns and the _pm Parquet-metadata sidecar. 9.4.1 closes the correctness gaps found since — both where those features meet Parquet storage and on the index path generally:

  • SELECT ... LIMIT -N over a covering index now returns the last N rows, not the first N — it was silently wrong, including with sym IN (...) and bind-variable limits. #7182
  • A posting index no longer loses rows after a failed O3 commit, where a purge could remove the previous seal's files before the replacement chain entry became durable. #7192
  • Adding a covering index when the most recent partition is Parquet no longer crashes and suspends the table. #7141
  • Covering-index builds now read Parquet column data correctly during seal, work on a WAL table's last partition, and stay within RSS_MEM_LIMIT on multi-GiB strides via streaming FSST encode/decode and a per-frame row cap. #7145
  • Indexed WHERE col = null lookups against an all-NULL SYMBOL row group in a Parquet partition return the correct rows again (O3 rewrite, ADD INDEX, and checkpoint-restore paths). #7146
  • A query that projects only a column added with ALTER TABLE ADD COLUMN after a partition was converted to Parquet now reads NULL instead of crashing or returning stale data. #7185
  • _pm sidecars generated by migration / backup-restore / attach now inline Parquet bloom-filter bitsets, so equality predicates on bloom-indexed columns no longer re-read data.parquet at plan time. #7148

See the posting index and covering index documentation. by @bluestreak01, @jerrinot, @nwoolmer and @RaphDal

Opt-in native memory caps for window functions and ORDER BY

Six new byte-denominated configuration keys bound native-memory growth in the CachedWindow record store, the LongTreeChain heaps (used by window functions and ORDER BY), and the ORDER BY sort heaps. They are uncapped by default — so existing deployments are unaffected — but setting any of them turns an unbounded growth into a clean LimitOverflowException with a hint naming the exact key to raise. The older page-count keys are deprecated but still honoured. by @puzpuzpuz in #7157

Performance

  • Materialized-view incremental refresh under out-of-order backfill: a cost-aware clustering pass skips pre-existing buckets that no transaction touched. In a 512-symbol view with a 12-hour O3 lag, refresh drops from ~160 ms to ~1.7 ms (up to ~90x); recent/small writes see little change. materialized_views() gains three columns exposing the cost model. by @nwoolmer in #7112
  • Materialized views no longer emit no-op WAL transactions when an incremental/period refresh finds nothing to do under base-table apply backlog — previously a single view could flood its WAL with millions of empty replace-range transactions, stalling replicas. by @puzpuzpuz in #7136
  • Parallel twap() and sparkline(): a batch-descriptor merge speeds up the common parallel and concurrent paths by ~2-3x. The high-cardinality memory-stress case (1M groups, ~10 obs/group) regresses ~15% as per-group state widens. by @mtopolnik in #7140
  • Parallel approx_percentile() for LONG arguments: low-precision aggregation moves onto an off-heap parallel histogram. by @mcadariu in #7084
  • Non-keyed GROUP BY now runs exclusively on the async factory; min/max over the designated timestamp short-circuit the column scan. Plan output changes for affected queries (see Behaviour changes). by @puzpuzpuz in #7102
  • Single-pass Parquet decode for covering-index builds: SYMBOL and covered columns decode together in one pass per row group, removing a full second decode and a disk round-trip. by @bluestreak01 in #7171
  • QWP query egress keeps reader partitions open (sequential/cached scan profile), cutting full-scan end-to-end latency by ~16% and lifting throughput ~19% in the egress benchmark. by @jerrinot in #7125

Bug fixes

SQL planner and execution

  • Fixed corr, stddev_pop/samp, var_pop/samp, and covar_pop/samp returning NULL on sparse-NULL data under parallel GROUP BY, caused by empty worker partials poisoning the merge. by @brunocalza in #7165
  • Fixed twap() and sparkline() silently returning wrong results under concurrent query load, where cross-query work-stealing left a slot's buffer in non-monotonic order. by @mtopolnik in #7126
  • Fixed joins on a SYMBOL key plus a UUID or DECIMAL key failing with an internal error instead of returning results. by @jerrinot in #7115
  • Fixed a rare JIT-compiler crash (SIGSEGV) when the allocator's search region drifted below a block end, via an upstream asmjit bound check. by @puzpuzpuz in #7173

Storage, Parquet and WAL

  • Fixed a crash (SIGSEGV) and boot-time crash loop when deduplicating a STRING dedup key whose per-partition data file has grown beyond 2 GiB — a 64-bit offset was being truncated to 32-bit. by @bluestreak01 in #7196
  • The WAL sequencer can now rebuild a bricked or version-mismatched _meta from the committed transaction log, ignoring uncommitted sidecar tails and keeping the registry token authoritative across table renames. by @jerrinot in #7105
  • CREATE MATERIALIZED VIEW ... TTL N months on a view with a derived partition is now validated up front and rejected when N months is not a whole multiple of the derived partition size (previously only hours-based TTL was checked). by @glasstiger in #7180
  • Fixed tables with a posting-indexed SYMBOL column getting stuck mid-switch when used with storage policy after conversion to Parquet. by @RaphDal in #7176

Protocols

  • QWP WebSocket upgrade (the 101 Switching Protocols response, and 4xx/426/421 reject bodies) now completes correctly when it cannot leave the socket in a single write, instead of tearing the connection down. by @bluestreak01 in #7129
  • QWP now drains the kernel recv buffer on graceful WebSocket close, so the CLOSE frame and its diagnostic reach the client instead of being destroyed by a TCP RST (clients saw ECONNRESET before). by @bluestreak01 in #7164
  • QWP egress now splits a query result that does not fit the HTTP send buffer (e.g. a large high-cardinality SYMBOL dictionary delta) across multiple batches instead of failing the query. by @kafka1991 in #7130
  • The SQL validation endpoint (/api/v1/sql/validate) is now side-effect free: it no longer enforces permissions, runs inline statements, or emits query-progress / error log lines and metrics. It does now resolve the target object, so validating a statement against a non-existent table reports the missing object rather than passing. by @glasstiger in #7124

Behaviour changes and upgrade notes

  • Parquet metadata regeneration on first start. The migration version bumps to 429; on first 9.4.1 startup, instances that already ran the 9.4.0 (428) migration regenerate their _pm sidecars to inline bloom filters. The cost scales with total Parquet partition count and is comparable to the original migration run. #7148
  • INT - FLOAT now returns FLOAT (was DOUBLE), matching +, *, /. A downstream cast near an f32 ulp boundary may round differently. Preserve the old behaviour with an explicit ::DOUBLE on either operand. #7021
  • Nested INT arithmetic in a LONG context now computes at 64-bit width. A query that relied on a 32-bit wrap of an inner INT product/sum will now see the long-precision answer; force the old behaviour with an explicit ::INT around the inner expression. #7021
  • STRING / VARCHAR <= null and >= null now return matching NULL rows instead of zero rows. Queries that relied on the previous empty result should filter with IS NOT NULL, or use < null / > null (still always zero rows). #7021
  • twap() rejects a non-designated-timestamp argument at compile time. Such a query previously ran and could return an incorrect result; it now fails with a clear error. #7140
  • EXPLAIN plan output changes for non-keyed aggregations (previously shown as GroupByNotKeyed Vectorized) and for min/max over the designated timestamp (now min_designated / max_designated). Tooling that parses plans verbatim should update. #7102

Changelist

  • feat(sql): add array_agg() aggregate for collecting double values into arrays by @javier in #6812
  • feat(sql): add regr_r2 coefficient of determination aggregate by @jovfer in #7104
  • feat(sql): add window function support for DECIMAL datatype by @kafka1991 in #7135
  • feat(sql): add byte caps for CachedWindow and ORDER BY native memory by @puzpuzpuz in #7157
  • feat(qwp): add deferred commit for transactional ingestion by @bluestreak01 in #7144
  • feat(qwp): expand ingest wire-type coverage and advertise batch cap by @bluestreak01 in #7108
  • perf(core): skip unchanged buckets on O3 incremental refresh by @nwoolmer in #7112
  • perf(sql): stop materialized views emitting no-op WAL transactions under base table backlog by @puzpuzpuz in #7136
  • perf(sql): speed up parallel twap() and sparkline() by @mtopolnik in #7140
  • perf(sql): parallelise low-precision approx_percentile for LONG arg by @mcadariu in #7084
  • perf(sql): remove vect group by factory and fix missing gaps in non-keyed async factory by @puzpuzpuz in #7102
  • perf(sql): single-pass parquet decode for covering index build by @bluestreak01 in #7171
  • perf(qwp): keep partitions open on egress to lower full-scan latency by @jerrinot in #7125
  • fix(sql): fix 55 correctness and resource-leak bugs surfaced by the new query fuzzer by @puzpuzpuz in #7021
  • fix(sql): fix 9 correctness and resource-leak bugs surfaced by stricter query assertions by @bluestreak01 in #7187
  • fix(core): fix crash deduplicating STRING keys in partitions over 2GB by @bluestreak01 in #7196
  • fix(core): read a column added after Parquet conversion as NULL by @bluestreak01 in #7185
  • fix(core): validate months-based TTL granularity on materialized views by @glasstiger in #7180
  • fix(core): fix storage policy for tables with posting indexes by @RaphDal in #7176
  • fix(sql): fix rare JIT compiler crash when allocator's search region drifts below block end by @puzpuzpuz in #7173
  • fix(sql): fix statistical aggregates returning NULL on sparse-NULL data by @brunocalza in #7165
  • fix(sql): make covering indexes work on Parquet partitions and bound RSS during seal by @nwoolmer in #7145
  • fix(qwp): drain recv buffer on WebSocket graceful close to prevent TCP RST by @bluestreak01 in #7164
  • fix(core): fix indexed NULL lookups against Parquet partitions by @bluestreak01 in #7146
  • fix(qwp): fix WebSocket handshake under partial socket writes by @bluestreak01 in #7129
  • fix(core): do not execute statements during SQL validation by @glasstiger in #7124
  • fix(core): fix crash adding a covering index when the latest partition is Parquet by @nwoolmer in #7141
  • fix(sql): return the last N rows for LIMIT -N over a covering index by @bluestreak01 in #7182
  • fix(core): prevent posting index wrong results after failed O3 commit by @jerrinot in #7192
  • fix(wal): recover sequencer metadata from committed log by @jerrinot in #7105
  • fix(qwp): allow query results larger than the HTTP send buffer by @kafka1991 in #7130
  • fix(sql): fix wrong twap() and sparkline() results under concurrent query load by @mtopolnik in #7126
  • perf(core): inline bloom filters into Parquet metadata generated by migration by @RaphDal in #7148
  • fix(sql): prevent internal errors in symbol hash joins by @jerrinot in #7115

Full Changelog: 9.4.0...9.4.1

19 hours ago
fluent-bit

Fluent Bit 4.2.5

https://fluentbit.io/announcements/v4.2.5/

What's Changed

Full Changelog: https://github.com/fluent/fluent-bit/compare/v4.2.4...v4.2.5

1 days ago
valkey

8.1.8

Upgrade urgency HIGH: There is a critical bug that may affect a subset of users.

Bug fixes

  • Fix ZDIFF algorithm 2 memory leak on early exit (#3342)
  • Strictly check CRLF when parsing querybuf (#2872)
  • Fix incorrect memory overhead calculation for watched keys (#3359)
  • Fix valkey-cli --cluster del-node for unreachable nodes (#3209)
  • Fix race condition during async client freeing with IO threading enabled (#3458)
  • Fix double free in stream consumer PEL loading with corrupt RDB data (#3498)
  • Fixes server crash when RDMA benchmark clients disconnect (#3448)
  • Fix misleading log "I/O error reading bulk count from PRIMARY: Success" (#3580)
  • Handle NULL pointer in streamTrim listpack delta calculation (#3591)
  • Fix Deferred Reply Placeholders in Active Deferred Buffers (#3578)
  • Add NULL check in updateSSLPendingFlag (#3641)
  • Fix heap-use-after-free in ACL LOAD when client free is deferred (#3800)
  • Redacting customer information when hide_user_data_from_log is true in rdb.c, networking.c, debug.c and t_hash (#3872)
  • Fix use-after-free in VM_RegisterClusterMessageReceiver (#3846)
  • Harden SENTINEL commands and config rewrite against control-character injection (#3847)
  • Fix CLUSTER SLOTS crash when called from module timer callback (#2915)

Full Changelog: https://github.com/valkey-io/valkey/compare/8.1.7...8.1.8

1 days ago
MeiliSearch

v1.45.2 🦒

🪲 Bug Fixes

  • Fix internal vector stores quantization config desync by @Kerollmops in https://github.com/meilisearch/meilisearch/pull/6411 We noticed issues when dumpless upgrading databases containing embedders from versions older than v1.33.1. This version fixes those databases by removing the corrupted embeddings from the impacted indexes.

Full Changelog: https://github.com/meilisearch/meilisearch/compare/v1.45.1...v1.45.2

1 days ago
timescaledb

2.27.2 (2026-06-02)

This release contains bug fixes since the 2.27.1 release. We recommend that you upgrade at the next available opportunity.

Bugfixes

  • #9895 Remove refresh policy check when adding columnstore policy
  • #9902 Fix wrong results and crashes when grouping by columns that are not in the SELECT list with vectorized aggregation or columnar index scan
  • #9908 Skip ColumnarIndexScan when the qual contains a SubPlan
1 days ago
seaweedfs

4.31

What's Changed

New Contributors

Full Changelog: https://github.com/seaweedfs/seaweedfs/compare/4.30...4.31

2 days ago
etcd

v3.7.0-rc.0

Please check out CHANGELOG for a full list of changes. And make sure to read our upgrade guides before upgrading etcd (there may be breaking changes).

For installation guides, please check out operating etcd. Latest support status for common architectures and operating systems can be found at supported platforms.

Linux
ETCD_VER=v3.7.0-rc.0

# choose either URL
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}

rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test

curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/etcd-download-test --strip-components=1 --no-same-owner
rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz

/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version
/tmp/etcd-download-test/etcdutl version

# start a local etcd server
/tmp/etcd-download-test/etcd

# write,read to etcd
/tmp/etcd-download-test/etcdctl --endpoints=localhost:2379 put foo bar
/tmp/etcd-download-test/etcdctl --endpoints=localhost:2379 get foo
macOS (Darwin)
ETCD_VER=v3.7.0-rc.0

# choose either URL
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}

rm -f /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test

curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-darwin-amd64.zip -o /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
unzip /tmp/etcd-${ETCD_VER}-darwin-amd64.zip -d /tmp && rm -f /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
mv /tmp/etcd-${ETCD_VER}-darwin-amd64/* /tmp/etcd-download-test && rm -rf mv /tmp/etcd-${ETCD_VER}-darwin-amd64

/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version
/tmp/etcd-download-test/etcdutl version
Docker

etcd uses gcr.io/etcd-development/etcd as a primary container registry, and quay.io/coreos/etcd as secondary.

ETCD_VER=v3.7.0-rc.0

rm -rf /tmp/etcd-data.tmp && mkdir -p /tmp/etcd-data.tmp && \
  docker rmi gcr.io/etcd-development/etcd:${ETCD_VER} || true && \
  docker run \
  -p 2379:2379 \
  -p 2380:2380 \
  --mount type=bind,source=/tmp/etcd-data.tmp,destination=/etcd-data \
  --name etcd-gcr-${ETCD_VER} \
  gcr.io/etcd-development/etcd:${ETCD_VER} \
  /usr/local/bin/etcd \
  --name s1 \
  --data-dir /etcd-data \
  --listen-client-urls http://0.0.0.0:2379 \
  --advertise-client-urls http://0.0.0.0:2379 \
  --listen-peer-urls http://0.0.0.0:2380 \
  --initial-advertise-peer-urls http://0.0.0.0:2380 \
  --initial-cluster s1=http://0.0.0.0:2380 \
  --initial-cluster-token tkn \
  --initial-cluster-state new \
  --log-level info \
  --logger zap \
  --log-outputs stderr

docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcd --version
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdctl version
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdutl version
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdctl endpoint health
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdctl put foo bar
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdctl get foo
2 days ago
etcd

v3.6.12

Please check out CHANGELOG for a full list of changes. And make sure to read upgrade guide before upgrading etcd (there may be breaking changes).

For installation guides, please check out operating etcd. Latest support status for common architectures and operating systems can be found at supported platforms.

Linux
ETCD_VER=v3.6.12

# choose either URL
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}

rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test

curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/etcd-download-test --strip-components=1 --no-same-owner
rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz

/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version
/tmp/etcd-download-test/etcdutl version

# start a local etcd server
/tmp/etcd-download-test/etcd

# write,read to etcd
/tmp/etcd-download-test/etcdctl --endpoints=localhost:2379 put foo bar
/tmp/etcd-download-test/etcdctl --endpoints=localhost:2379 get foo
macOS (Darwin)
ETCD_VER=v3.6.12

# choose either URL
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}

rm -f /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test

curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-darwin-amd64.zip -o /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
unzip /tmp/etcd-${ETCD_VER}-darwin-amd64.zip -d /tmp && rm -f /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
mv /tmp/etcd-${ETCD_VER}-darwin-amd64/* /tmp/etcd-download-test && rm -rf mv /tmp/etcd-${ETCD_VER}-darwin-amd64

/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version
/tmp/etcd-download-test/etcdutl version
Docker

etcd uses gcr.io/etcd-development/etcd as a primary container registry, and quay.io/coreos/etcd as secondary.

ETCD_VER=v3.6.12

rm -rf /tmp/etcd-data.tmp && mkdir -p /tmp/etcd-data.tmp && \
  docker rmi gcr.io/etcd-development/etcd:${ETCD_VER} || true && \
  docker run \
  -p 2379:2379 \
  -p 2380:2380 \
  --mount type=bind,source=/tmp/etcd-data.tmp,destination=/etcd-data \
  --name etcd-gcr-${ETCD_VER} \
  gcr.io/etcd-development/etcd:${ETCD_VER} \
  /usr/local/bin/etcd \
  --name s1 \
  --data-dir /etcd-data \
  --listen-client-urls http://0.0.0.0:2379 \
  --advertise-client-urls http://0.0.0.0:2379 \
  --listen-peer-urls http://0.0.0.0:2380 \
  --initial-advertise-peer-urls http://0.0.0.0:2380 \
  --initial-cluster s1=http://0.0.0.0:2380 \
  --initial-cluster-token tkn \
  --initial-cluster-state new \
  --log-level info \
  --logger zap \
  --log-outputs stderr

docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcd --version
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdctl version
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdutl version
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdctl endpoint health
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdctl put foo bar
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdctl get foo
2 days ago
etcd

v3.5.31

Please check out CHANGELOG for a full list of changes. And make sure to read upgrade guide before upgrading etcd (there may be breaking changes).

For installation guides, please check out operating etcd. Latest support status for common architectures and operating systems can be found at supported platforms.

Linux
ETCD_VER=v3.5.31

# choose either URL
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}

rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test

curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/etcd-download-test --strip-components=1 --no-same-owner
rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz

/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version
/tmp/etcd-download-test/etcdutl version

# start a local etcd server
/tmp/etcd-download-test/etcd

# write,read to etcd
/tmp/etcd-download-test/etcdctl --endpoints=localhost:2379 put foo bar
/tmp/etcd-download-test/etcdctl --endpoints=localhost:2379 get foo
macOS (Darwin)
ETCD_VER=v3.5.31

# choose either URL
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}

rm -f /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test

curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-darwin-amd64.zip -o /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
unzip /tmp/etcd-${ETCD_VER}-darwin-amd64.zip -d /tmp && rm -f /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
mv /tmp/etcd-${ETCD_VER}-darwin-amd64/* /tmp/etcd-download-test && rm -rf mv /tmp/etcd-${ETCD_VER}-darwin-amd64

/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version
/tmp/etcd-download-test/etcdutl version
Docker

etcd uses gcr.io/etcd-development/etcd as a primary container registry, and quay.io/coreos/etcd as secondary.

ETCD_VER=v3.5.31

rm -rf /tmp/etcd-data.tmp && mkdir -p /tmp/etcd-data.tmp && \
  docker rmi gcr.io/etcd-development/etcd:${ETCD_VER} || true && \
  docker run \
  -p 2379:2379 \
  -p 2380:2380 \
  --mount type=bind,source=/tmp/etcd-data.tmp,destination=/etcd-data \
  --name etcd-gcr-${ETCD_VER} \
  gcr.io/etcd-development/etcd:${ETCD_VER} \
  /usr/local/bin/etcd \
  --name s1 \
  --data-dir /etcd-data \
  --listen-client-urls http://0.0.0.0:2379 \
  --advertise-client-urls http://0.0.0.0:2379 \
  --listen-peer-urls http://0.0.0.0:2380 \
  --initial-advertise-peer-urls http://0.0.0.0:2380 \
  --initial-cluster s1=http://0.0.0.0:2380 \
  --initial-cluster-token tkn \
  --initial-cluster-state new \
  --log-level info \
  --logger zap \
  --log-outputs stderr

docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcd --version
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdctl version
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdutl version
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdctl endpoint health
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdctl put foo bar
docker exec etcd-gcr-${ETCD_VER} /usr/local/bin/etcdctl get foo