Skip to content

Releases: dragonflydb/dragonfly

v1.39.0

09 Jun 10:38
699862e

Choose a tag to compare

Dragonfly v1.39.0

This release delivers a significant leap in full-text search capability — FT.HYBRID fuses vector similarity with text queries, exact phrase matching with slop arrives, Porter stemming is on by default for TEXT fields, and BM25STD/TFIDF scoring with WITHSCORES support rounds out a deeply improved search engine. Performance improves across the board: PubSub reply batching cuts syscalls by 24–70% and raises throughput up to +12% RPS, INFO REPLICATION becomes fully lock-free, and a new ShardedHashMap replaces the global RCU ChannelStore for pub/sub. Security is tightened with multiple Lua sandbox hardening patches, RESP injection prevention, and PII-safe error logging. Tiered hashes are now mutable. A significant sweep of zombie-key cleanup fixes closes a class of bugs where lazy field expiry across SORT, ZUNIONSTORE, ZINTERSTORE, SHRINK, and hash TTL commands left empty containers in the keyspace.

Highlights

  • Added FT.HYBRID combining full-text and vector similarity search with LINEAR and RRF score fusion strategies, capping a major release cycle of search improvements (#7420)
  • PubSub, Monitor, and Invalidation replies are now batched per wakeup, delivering up to +12% RPS and 24–70% fewer syscalls at pipeline depths 1–500 (#7479)
  • Tagged chunk serialization splits large objects across snapshot and replication boundaries so they can be reassembled correctly even with interleaved journal entries (#7416, #7070)

Search

  • Adds FT.HYBRID combining full-text and VSIM search via LINEAR (ALPHA/BETA weighted sum of normalized scores) and RRF (Reciprocal Rank Fusion) strategies, with HNSW KNN and range-based vector queries, YIELD_SCORE_AS aliasing, LOAD projection, and FT.PROFILE support (#7420)
  • Adds exact phrase queries ("hello world") and approximate phrase matching with slop ("..."~N), backed by per-document token positions stored in compressed posting lists; BM25 scoring updated for phrase semantics (#7319)
  • TEXT fields now apply Porter stemming by default via the vendored Snowball/libstemmer library; per-field NOSTEM, index-level LANGUAGE (default english), and per-document LANGUAGE_FIELD are all supported; FT.INFO surfaces the new flags (#7295)
  • Adds BM25STD (Okapi BM25) relevance scoring engine with per-field TF and document-length tracking for accurate normalization; results can be ranked when a scorer is activated (#7101)
  • Adds TFIDF (TF × ln(N/n)) and TFIDF.DOCNORM (additionally normalized by field length) as new scorer options for FT.SEARCH, FT.PROFILE, and FT.AGGREGATE; scorer dispatch refactored to a function-pointer table (#7200)
  • FT.SEARCH now supports WITHSCORES and SCORER parameters; FT.AGGREGATE gains ADDSCORES to inject a __score field enabling downstream GROUPBY/SORTBY/REDUCE on relevance (#7181)
  • HNSW vector index memory is now tracked in the search_used memory class and reported in dragonfly_memory_used_bytes via an atomic capacity-based footprint counter (#7205)

Performance

  • PubSub, Monitor, and Invalidation control-path replies are now accumulated in the send buffer and flushed together per wakeup rather than one sendmsg per message; single-message wakeups still flush immediately [+3% RPS at pipeline=1, +12% at pipeline=10, −24% to −70% syscalls at pipeline=1–500] (#7479)
  • INFO REPLICATION and replica memory stats are now served lock-free via per-proactor thread-local snapshots updated on every mutation, eliminating global mutex and per-replica shared-lock fan-out (#7348)
  • Replaced the global RCU-based ChannelStore with a ShardedHashMap (16 independent shard locks), removing the pool-wide broadcast on every subscribe/unsubscribe (#7174)
  • NotifyWatchQueue exits in O(1) when a watched key is absent (previously O(N) over all waiters), directly benefiting BLPOP, BZPOPMIN, and XREAD workloads (#7225)
  • Long-running container iteration commands (LRANGE, SMEMBERS, ZRANGE, HGETALL, etc.) now yield the shard fiber periodically; configurable via --container_iteration_yield_interval_usec (default 500 µs, 0 to disable) (#7391)
  • Integrates OAHSet as an alternative in-memory set backend selectable via --use_oah_set; threaded through RDB save/load, async deletion, defragmentation, and SHRINK (#7246)
  • Adds foundational zero-copy GET infrastructure to CompactObj and LargeString: TryBorrow() returns an encoded view with Copy-on-Write semantics; a thread-local pin registry defers buffer deallocation until all readers finish (#7412)
  • Connections that occasionally receive large commands now trim parse buffers exceeding 256 KiB at more than 2× actual utilization, preventing permanent oversized memory holds (#7378)

Replication

  • Adds serialization_tagged_chunks flag enabling the RDB serializer to split large entries into tagged chunks with envelope IDs; compression is applied per-blob; a related list-decoding crash during chunked load is also fixed (#7416)
  • Implements tagged chunk loading in the RDB loader with per-stream continuation state, supporting interleaved chunks from different objects and cross-database-boundary reassembly (#7070)
  • Four new Prometheus metrics are now emitted on replica instances at /metrics: dragonfly_master_link_status, dragonfly_master_last_io_seconds_ago, dragonfly_sync_in_progress, and dragonfly_slave_repl_offset (#7069)

Cluster

  • Adds --cluster_coordinator_connect_timeout_ms and --cluster_coordinator_response_timeout_ms flags to control coordinator-to-shard timeouts (previously hard-coded at 3000 ms) (#7221)
  • Cluster config validation now rejects invalid migration configurations at parse time: wrong target masters, duplicate targets, empty or out-of-range slot sets, and overlapping migration ranges (#7210)

Commands

  • CLIENT LIST now supports TYPE <normal|master|replica|slave|pubsub> and ID <id> [id …] filter arguments; outbound replication links are surfaced as TYPE master entries; CLIENT KILL ID on a master-link ID returns a descriptive error directing users to REPLICAOF NO ONE (#7377)
  • DEBUG TRAFFIC now supports per-listener recording (LISTENER <main|memcache|admin>), full Memcache protocol capture and replay (SET/GET/CAS/INCR/GAT/etc. with flags, expiry, and CAS tokens), and a v3 file format; v2 files remain readable (#7192)
  • DEBUG TRAFFIC START <path> REPLICA records the replication stream received by a replica from its master; fails with a clear error on standalone/master instances (#7217)
  • BF.SCANDUMP iteratively exports a Scalable Bloom Filter in chunks of up to 16 MiB, returning (cursor, data) pairs until cursor=0 signals end-of-stream (#7092)
  • BF.LOADCHUNK reconstructs an SBF from chunks produced by BF.SCANDUMP, completing the SCANDUMP/LOADCHUNK round-trip; guards prevent other BF commands from operating on a partially-loaded filter (#7169)
  • BGSAVE now accepts the optional SCHEDULE subcommand (case-insensitive) for Redis client compatibility; concurrent saves are still rejected rather than queued (#7286)
  • dfly_bench gains --json_out_file to write a memtier_benchmark-compatible latency JSON report including per-operation aggregate stats (count, ops/sec, average/min/max, p50/p99/p99.9) and a per-second time-series (#7269)

Security

  • The Lua load() built-in is now wrapped to enforce text-only mode ("t"), closing a sandbox escape vector where a malicious script could supply binary Lua bytecode to bypass restrictions (#7376)
  • Lua sandbox hardened: rawset, setmetatable, and getmetatable are overridden to block access to _G and all global library tables; guard metatables are attached to prevent replacement or corruption across script executions (#7370)
  • Error logs from failed commands no longer include user-supplied PII: arguments are truncated at 128 bytes with a byte-count suffix, at most 31 args are logged, EVAL KEYS/ARGV are omitted, and AUTH/ACL subcommands are fully redacted (#7338)
  • INFO ACL section added, exposing aggregate registry metrics (acl_num_users, password/glob counts, estimated acl_total_bytes) maintained incrementally without holding the registry write lock (#7149)

Cloud & Storage

  • S3 snapshot storage is now available in all builds using helio's native S3 client by default; the AWS SDK backend remains available via WITH_AWS + --s3_use_helio_client=false; builds without WITH_AWS no longer exit on s3:// paths (#7180)
  • Azure Blob Storage snapshot backend fully implemented: az:// URIs are correctly routed, OpenWriteFile/OpenReadFile use the cloud::azure API, and cursor-based pagination fixes truncation for large buckets (#7131)
  • Hash write commands (HSET, HDEL) now operate on hashes offloaded to tiered (disk-backed) storage: the serialized listpack is read from disk, mutated in-place, and re-stashed with I/O backpressure (#6085)
  • S3 endpoint override (e.g. for MinIO) is now passed directly to AwsCredsProvider instead of setting AWS_S3_ENDPOINT in the process environment, eliminating side effects for other processes (#7408)

Bug Fixes

Replication & Persistence

  • Fixed slave_repl_offset reporting zero in INFO REPLICATION when replicating from a Redis/Valkey master; offset is now correctly populated from repl_offs_ (#7517)
  • Fixed a TOCTOU race where a DflyConn_ fiber could violate the serializer's fiber-identity check during BGSAVE while Lua EVAL scripts ran concurrently (#7499)
  • Fixed single-shard batch scheduling (ScheduleBatchInShard) allowing a journal DEL entry to execute before the RDB loader finished creating the key on a shard (#7507)
  • Fixed SBF (Scalable Bloom Filter) serialization mismatch where SaveString encoding was read back as raw bytes, crashing Dragonfly in Renamer::FinalizeRename on COPY/DUMP (#7475)
  • Fixed data loaded via DFLY LOAD not propagating to replicas; the journal ring buffer is now cleared and reconnecting ...
Read more

v1.38.1

28 Apr 08:01
8dbbd4f

Choose a tag to compare

This is a patch release

What's Changed

  • fix(server): Re-use journal executor (#7201)
  • test(connection): add a fix for FIN_WAIT_2 leak bug with BLPOP (#7224)
  • fix: avoid O(n) scans in NotifyWatchQueue (#7225)

Full Changelog: v1.38.0...v1.38.1

v1.38.0

14 Apr 07:04
31a8fd3

Choose a tag to compare

Dragonfly v1.38.0

This release is a major one with lots of significant improvements and stability fixes.
It may behave differently due to changes in its core data structures.
We worked hard to avoid any regressions so please let us know if you observe degradation around item expiry behavior, replication or backups.

Important stability fixes and changes:

Top-K command family (TOPK.*): RedisBloom-compatible heavy-hitter sketch with
RDB persistence. (#6920, #6931, #6932, #6950)

Count-Min Sketch family (CMS.*): Full CMS with INITBYDIM, INITBYPROB,
INCRBY, QUERY, MERGE, INFO. RDB persistence. (#6867, #6888, #6896, #6897)

~26% memory reduction for TTL workloads: Expire table eliminated, expiry embedded
in CompactKey via SDS_TTL_TAG. 10M keys: 900 MB -> 665 MB. (#6923, #6925, #6933)

HTTL command: Returns remaining TTL for specific hash fields. (#6879)

VECTOR_RANGE search: Radius-based vector similarity queries in FT.SEARCH and
FT.AGGREGATE for both FLAT and HNSW indexes, with optional YIELD_DISTANCE_AS.
(#6880, #6898, #6938)

FT.AGGREGATE: FILTER, APPLY, DIALECT, KNN: Full expression-based filtering,
computed fields, dialect selection, and KNN steps in the aggregation pipeline.
(#6968, #6982, #7066)

Smarter KNN prefilter: Falls back to brute-force scan when prefilter result set
is small. (#6730)

Replica expired-key deletion: Replicas proactively delete expired keys on reads.
--replica_delete_expired (default true). (#6985)

New Prometheus metrics: Pipeline latency histogram (dragonfly_pipeline_latency_seconds),
TLS handshake counter (tls_handshakes_total), stream access patterns
(stream_accesses_total), pipeline blocking counter. (#6688, #7015, #6767, #6685)

EKS Pod Identity for S3: AWS credential chain supports EKS Pod Identity and ECS
task roles. (#6917)

Early TLS filter and TCP_DEFER_ACCEPT: Drops zombie connections at OS level before
allocating fiber/OpenSSL state. (#6857)

Memcached io_loop_v2 enabled by default*: Async I/O with deferred replies. (#6700)

Incremental SBF replication: Scalable Bloom Filter chunks flushed incrementally,
bounding peak memory. (#7034)

What's Changed

  • chore(server): Extend script slowlog stats by @dranikpg in #6656
  • test(ci): exclude flaky BullMQ tests by @vyavdoshenko in #6673
  • feat(fuzz): Add LLM-guided PR fuzzing with targeted seed generation by @vyavdoshenko in #6666
  • refactor(journal): replace Journal class with free functions by @romange in #6672
  • fix(search): Fix HNSW index creation failure, logs, drop by @dranikpg in #6662
  • refactor: clean includes by @BorysTheDev in #6679
  • chore: remove facade/acl_commands.h by @kostasrim in #6682
  • fix: improve fuzz-pr crash detection and artifact packaging by @vyavdoshenko in #6686
  • feat(tiering): Use Future::IsResolved to check if delayed entry is resolved by @mkaruza in #6665
  • test: mark heavy skipped tests as large instead of skip by @vyavdoshenko in #6675
  • feat: add pipeline latency histogram and Prometheus SUMMARY export by @romange in #6688
  • refactor: move methods from OAHEntry to OAHSet by @BorysTheDev in #6692
  • chore: remove duplicate info reported by "memory stats" by @romange in #6696
  • server: Collect stats for why defragmentation was skipped by @abhijat in #6680
  • fix: shrink memory usage for journaling items by @romange in #6695
  • ci: exclude flaky BullMQ getWorkers shared connection test by @vyavdoshenko in #6697
  • fix(tiering): Track all keys mutation callback for cluster migration by @mkaruza in #6691
  • refactor: remove static fields from rdb_load by @BorysTheDev in #6684
  • fix(tiering): Increase write depth by @dranikpg in #6705
  • refactor(mc): async MGET/GAT by @glevkovich in #6674
  • chore(ci): Replace direct push with PR for helm chart updates by @vyavdoshenko in #6717
  • fix: validate stream command arguments to prevent crashes by @vyavdoshenko in #6718
  • fix(fuzz): skip missing RECORD files in replay_crash.py by @vyavdoshenko in #6719
  • chore: Skip KNN search if prefilter is empty by @mkaruza in #6720
  • perf(seeder): batch STRING hashing with MGET to reduce tiering latency by @romange in #6721
  • test: add test for replication HNSW index by @BorysTheDev in #6722
  • skip tiering tests by @dranikpg in #6723
  • ci: migrate ioloop-v2-regtests to OIDC for AWS auth by @AdiCloudbit-DevOps in #6725
  • test: skip test_hnsw_search_replication_with_network_disruptions by @BorysTheDev in #6729
  • feat: add RM command skeleton (phase 1) by @romange in #6731
  • chore: add pipeline_blocking_commands_total counter by @kostasrim in #6685
  • feat(set_family): Reserve vector on OpInter in advance by @abhijat in #6736
  • ci: add memcache fuzzing to regular campaign by @vyavdoshenko in #6735
  • test: consolidate slow marker into large by @vyavdoshenko in #6734
  • feat(dash): segment merging by @kostasrim in #6676
  • server: move blob loading logic into respective family classes by @romange in #6713
  • feat(facade): enable experimental_io_loop_v2 by default and clean CI by @glevkovich in #6700
  • core: Fix page usage accounting by @abhijat in #6737
  • chore: do not reconcile slots after dfly takeover if cluster config updated by @kostasrim in #6728
  • fix: orphan streams on error in OpCreate and OpAdd by @kostasrim in #6744
  • fix: crash in SetFullJson when overwriting string key with JSON by @vyavdoshenko in #6750
  • fix(server): flush replies on encountering blocking command in pipeline by @abhijat in #6743
  • server: Add summary view to memory arena by @abhijat in #6677
  • chore: stream family boilerplate to a function by @kostasrim in #6748
  • fix: prevent SIGFPE in DEBUG POPULATE when val_size is 0 by @vyavdoshenko in #6754
  • feat: implement RM scan-and-delete logic (phase 2) by @romange in #6732
  • refactor: move stream functions from t_stream.c to their call sites by @romange in #6703
  • ci: add optional memcache smoke fuzzing to PR workflow by @vyavdoshenko in #6758
  • feat(server): Get and set byte at index position in string object by @mkaruza in #6752
  • refactor: move stream alloc/free into compact_object and fix rdb_load cleanup by @romange in #6759
  • fix: return WOULD_BLOCK for STATS/VERSION in MC pipeline by @vyavdoshenko in #6762
  • ci: extract BullMQ skipped tests into a documented file by @vyavdoshenko in #6756
  • chore: Retrieve single byte for GETBIT command by @mkaruza in #6757
  • fix(bitops): Fetch only single byte for SETBIT operation by @mkaruza in #6745
  • fix: prevent empty hash on HINCRBYFLOAT with NaN/Inf by @vyavdoshenko in #6772
  • chore: revert our custom check-fails in mimalloc by @romange in #6774
  • json: Add stats for interned string pool by @abhijat in #6701
  • feat(server): add stream access pattern metrics by @romange in #6767
  • feat: add deffered queue for hnsw write ops by @BorysTheDev in #6746
  • feat(search): Use filtered search when prefilter result size is small by @mkaruza in #6730
  • chore: upload coverage by @kostasrim in #6747
  • tests: Protect connections with mutex by @abhijat in #6777
  • fix(search): use 2D vectors in HnswSubsetKnnTest/CompareWithFilteredKnn f or COS...
Read more

v1.37.2

26 Mar 07:49
9eee1e1

Choose a tag to compare

This is a patch release

What's Changed

  • fix(json): JSON.NUMINCRBY negative result overflow (#6981)
  • fix(streams): crash for XREAD BLOCK with replication (#6980)
  • fix(bitops): Improve performance of SETBIT operation (#6745)

Full Changelog: v1.37.0...v1.37.2

v1.37.0

23 Feb 10:50
aa35ea8

Choose a tag to compare

Dragonfly v1.37.0

Important stability fixes and changes:

  • Significant memory reduction around json documents #6511
  • Vector search memory usage is 40% less with hash map documents: #6436 #6437
  • Support of SORT command - including BY and GET options.
  • Several bug fixes around streams: #6506 #6492 #6532
  • Added support for DIGEST and DELEX commands: #6328

What's Changed

Read more

v1.36.0

07 Jan 11:23
65c71bd

Choose a tag to compare

Dragonfly v1.36.0

Important stability fixes and changes:

  1. Support Global Vector index #6103
  2. Support unicode tags in #6127
  3. django-cacheops compatibility fixes: #6123 #6129
  4. better memory defragmentation for json objects: #6240 #6276

What's Changed

Read more

v1.35.1

25 Nov 16:20
a8c096c

Choose a tag to compare

This is a patch release

What's Changed

  • fix(tiering): improvements around tiering stability #6040 #6086 #6067
  • fix(server): replica rejects replicating from itself #6097

Full Changelog: v1.35.0...v1.35.1

v1.34.2

14 Oct 16:04
00f52dc

Choose a tag to compare

This is a patch release

It is strongly advised to update to this version if you use 1.34.0 / 1.34.1 due to regression when Dragonfly runs in cache mode

What's Changed

  • fix(evicition): Don't accumulate deleted bytes if there is no RSS evi… by @BorysTheDev in #5908

Full Changelog: v1.34.1...v1.34.2

v1.34.1 (Use with caution - see known issues in description)

18 Sep 19:50
cae4e15

Choose a tag to compare

This is a patch release

Known issues

#5899
#5891

What's Changed

  • fix: prometheus is unable to scrape the /metrics endpoint #5829

Full Changelog: v1.34.0...v1.34.1

v1.34.0 (Use with caution - see known issues in description)

17 Sep 23:33
65acd60

Choose a tag to compare

Dragonfly v1.34.0

Known issues

#5899
#5891

Important stability fixes and changes:

What's Changed

Huge thanks to all the contributors! ❤️

New Contributors

Full Changelog: v1.33.0...v1.34.0