Library / SDK
petergoldstein/dalli avatar
petergoldstein/dalli

Dalli 5.1: A Ruby memcached client with failover, tracing, and a Marshal footgun

High performance memcached client for Ruby. Valid examples: :, /, |, ., -, _, # Security Note By default, Dalli uses Ruby's Marshal for serialization.

3,113 stars468 forksRubyMIT

At a glance

What is it?
Dalli is a pure Ruby memcached client that handles failover, serialization, compression, TLS, and OpenTelemetry tracing. Version 5.1 requires Ruby 3.3+ and memcached 1.6.27+, and it defaults to Marshal serialization, which is a security risk if you cache untrusted data.
Who is it for?
Adopt Dalli if you run Ruby 3.3+ with memcached 1.6.27+ and need a battle-tested pure Ruby client with failover, TLS, and automatic OpenTelemetry tracing. Do not use it if you cannot upgrade your memcached servers to 1.6.27 or if you cache user-controlled data without switching the default Marshal serializer.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 30 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 14, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What Dalli solves and who should use it

Dalli is a pure Ruby client for memcached. It solves the problem of talking to a memcached cluster from Ruby without native extensions, while handling the messy parts of production caching: server failover, connection pooling, serialization, compression, and TLS. The intended audience is Ruby application developers, especially those on Rails or Sinatra, who need a reliable cache layer. The README emphasizes high performance and thread safety, which matters for concurrent web servers. If you are already using memcached and want a client that stays current with Ruby and memcached releases, Dalli is a direct fit. It is also a reasonable choice if you want OpenTelemetry tracing without adding manual instrumentation code.

How Dalli handles failover and connection management

Dalli supports simple and complex memcached configurations, including failover between instances. The exact failover mechanism is not detailed in the README, but the option exists and is listed among supported features. The client can operate in two thread-safe modes: using a connection pool, or using the Dalli client in threadsafe mode. This is a design choice that affects how you structure your application. The connection pool approach is common in Ruby, but the threadsafe mode might be simpler for low-concurrency cases. The documentation does not specify the failover algorithm, so you should test how it behaves when a server goes down mid-request. Based on the repository layout, the client likely maintains a list of servers and retries operations on the next available one, but that is an inference from the feature list, not a confirmed detail.

Getting started: installation and basic usage

Dalli is distributed as a gem. You install it by adding `gem 'dalli'` to your Gemfile and running `bundle install`. The README shows a simple client creation: `Dalli::Client.new('localhost:11211')`. You can pass options like `namespace` and `namespace_separator`. For example, `Dalli::Client.new('localhost:11211', namespace: 'myapp')` prefixes all keys with `myapp:`. You can also use a dynamic namespace with a Proc, evaluated on each operation: `Dalli::Client.new('localhost:11211', namespace: -> { "tenant:#{Thread.current[:tenant_id]}" })`. The namespace separator defaults to a colon, but you can change it to a single non-alphanumeric character like `/` or `|`. The README shows `namespace_separator: '/'` for keys like `myapp/foo`. For development, you can run `bin/setup` to install dependencies and `bin/console` for an interactive prompt.

Serialization security: the Marshal default

The most important caveat in the README is the security note: by default, Dalli uses Ruby's Marshal for serialization. Deserializing untrusted data with Marshal can lead to remote code execution. This is a genuine failure mode. If your application caches user-controlled data, an attacker could craft a malicious payload that executes code when Dalli deserializes it. The README suggests using a safer serializer, such as JSON: `Dalli::Client.new('localhost:11211', serializer: JSON)`. This is a simple fix, but it is not automatic. You must remember to configure it. The trade-off is that JSON cannot serialize all Ruby objects, so you may need to adjust what you store. This is a case where the default is convenient but dangerous, and the documentation is honest about it. If you are adopting Dalli, plan to set a safe serializer from day one unless you are certain all cached data is trusted.

OpenTelemetry tracing with zero overhead when absent

Dalli automatically instruments operations with OpenTelemetry when the SDK is present. You do not need to configure anything beyond adding the OpenTelemetry gems to your application. The README lists the gems: `opentelemetry-sdk` and `opentelemetry-exporter-otlp` or your preferred exporter. When loaded, Dalli creates spans for single-key operations like `get`, `set`, `delete`, and `incr`, as well as multi-key operations like `get_multi` and `set_multi`. Spans include attributes such as `db.system: memcached` and `db.operation`. Single-key operations also include `server.address`, which is useful for debugging which server handled a request. Multi-key operations include cache efficiency metrics: `db.memcached.key_count`, `db.memcached.hit_count`, and `db.memcached.miss_count`. Errors are recorded on spans and re-raised. You can disable instrumentation at runtime with `Dalli::Instrumentation.disable!` or assign a custom tracer. The README claims zero overhead when OpenTelemetry is not present, because the tracing code checks once at startup and bypasses all logic. That is a strong claim, but it is plausible given the check-once design. If you are already using OpenTelemetry, this feature saves you from writing manual spans.

Version requirements and the meta protocol constraint

Dalli 5.1 requires Ruby 3.3 or later, and memcached 1.6.27 or later. The README is explicit that earlier 1.6.x servers are not supported. The reason is technical: the meta protocol rejects unknown flags outright, so features added after a server's release fail with `CLIENT_ERROR invalid flag` rather than degrading gracefully. This is a hard constraint. If you are on an older memcached version, you cannot use Dalli 5.1 without upgrading your cache servers. This is a significant operational consideration. The README states that Dalli is tested against both the minimum supported memcached version and the latest release, which is good practice, but it means you need to keep your memcached infrastructure current. If you cannot upgrade memcached, you will need to pin an older Dalli version, but the README does not specify which versions support older servers.

Alternatives and how they differ

The main alternative to Dalli is the `memcached` gem, which is a native extension wrapper around libmemcached. The difference in approach is significant: `memcached` uses C bindings for performance, while Dalli is pure Ruby. This means Dalli is easier to install on platforms where compiling native extensions is problematic, but it may be slower for high-throughput workloads. Another alternative is the `memcache-client` gem, but it is largely unmaintained. For Rails applications, the `cache_store` configuration can use Dalli directly, but you could also use `redis` as a cache backend, which changes the protocol and feature set entirely. Redis offers different data structures and persistence options, but it is not a drop-in replacement for memcached. If you need the memcached protocol and want to avoid native dependencies, Dalli is the practical choice. If raw performance is your top priority and you can handle native extensions, `memcached` might be worth benchmarking, though it has not seen recent releases.

Maintenance, licensing, and upgrade costs

Dalli is licensed under the MIT License, which is permissive and allows commercial use. The repository is actively maintained, with the last push in August 2026 and a recent v5.1.0 release. The README credits Mike Perham as the original author and Peter M. Goldstein as the current maintainer. Upgrading from 4.x to 5.x requires reading the `5.0-Upgrade.md` guide, which the README links to. The main upgrade cost is the memcached version requirement: you must be on 1.6.27 or later. There is also the serializer security change: if you were relying on Marshal, you need to evaluate your data and possibly switch to JSON. The OpenTelemetry instrumentation is a new feature in 5.x, so if you upgrade, you may see new spans in your tracing backend. The maintenance burden is low if you stay current with Ruby and memcached releases, but the project's requirement for recent versions means you cannot lag too far behind.

Editorial conclusion

Adopt Dalli if you run Ruby 3.3+ with memcached 1.6.27+ and need a battle-tested pure Ruby client with failover, TLS, and automatic OpenTelemetry tracing. Do not use it if you cannot upgrade your memcached servers to 1.6.27 or if you cache user-controlled data without switching the default Marshal serializer. Before adopting, verify your memcached version meets the 1.6.27 minimum and replace the default serializer with JSON or another safe format if your cache holds untrusted input.

Official sources

  1. Official README
  2. Project repository
  3. Release notes
Community notes

Community notes