Dalli: a pure Ruby memcached client for Rails and Ruby services
High performance memcached client for Ruby. Valid examples: :, /, |, ., -, _, # Security Note By default, Dalli uses Ruby's Marshal for serialization.
At a glance
- What is it?
- Dalli is a pure Ruby client for memcached, maintained by Peter M. Goldstein and released under the MIT licence. Its defaults are fast but they are also the thing you have to check first: Marshal serialization and a hard minimum of memcached 1.6.27.
- Who is it for?
- Adopt Dalli if you run Ruby 3.3 or later against memcached 1.6.27 or later and want a client that handles failover, namespaces and optional OpenTelemetry tracing without a native extension. Do not adopt it if you are pinned to an older 1.6.x memcached, because the README states the meta protocol rejects unknown flags with CLIENT_ERROR invalid flag instead of degrading, or if you cache user-controlled values and cannot switch the serializer away from Marshal.
- 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 5 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 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Dalli is for, and who ends up installing it
Dalli is a memcached client written in pure Ruby. The README describes it as "a high performance pure Ruby client for accessing memcached servers", and the repository is maintained by Peter M. Goldstein, with Mike Perham credited as the original author. The target user is a Ruby or Rails team that already runs memcached and wants to talk to it from application code without loading a C extension.
The feature list is aimed at production caches rather than toy scripts: simple and complex memcached configurations, failover between instances, control over serialization and compression, thread-safe operation either through a connection pool or in threadsafe mode, SSL/TLS connections, and OpenTelemetry tracing that activates automatically when the SDK is present. If your caching layer is a single localhost memcached and a single process, Dalli is more client than you need. If you have several memcached nodes, several tenants sharing one cache, or a tracing pipeline you want cache spans to land in, the feature set starts to line up with the problem.
Namespaces, separators and how keys actually reach the server
The mechanism most teams touch first is the namespace. Passing namespace: 'myapp' prefixes every key, which keeps two applications or two environments from colliding inside one memcached instance. Dalli also accepts a Proc, evaluated on each operation, so a tenant identifier can be resolved per request rather than fixed at boot. That is the difference between a static prefix and per-tenant partitioning, and it is the reason the option takes a callable at all.
The separator defaults to a colon, and namespace_separator changes it. The README constrains this tightly: the separator must be a single non-alphanumeric character, with :, /, |, ., -, _ and # given as valid examples. That restriction matters if you are trying to match a key convention already used by another language's client, because you cannot pass a multi-character separator to make the formats line up.
Serialization sits underneath all of this. By default Dalli uses Ruby's Marshal, and the README's security note is direct about the consequence: deserializing untrusted data with Marshal can lead to remote code execution. For caches holding user-controlled values, the README points at serializer: JSON as the safer choice. This is a default that favors speed and Ruby object fidelity over safety, and it is the single configuration decision worth making before the first deploy rather than after.
Install Dalli and run a first cache write
Dalli installs as a gem, and the README's development section gives the command for installing it onto your local machine. After checking out the repo, bin/setup installs dependencies and bin/console opens an interactive prompt.
bundle exec rake installOnce it is available, constructing a client is a single call against a host and port. The README's namespace example uses localhost on the default memcached port:
# All keys will be prefixed with "myapp:"
Dalli::Client.new('localhost:11211', namespace: 'myapp')The namespace option prefixes every key with myapp:, which is what keeps two applications or two environments apart inside one memcached instance. The README also shows the separator being changed, so the prefix uses a slash instead of a colon:
# Keys will be prefixed with "myapp/" instead of "myapp:"
Dalli::Client.new('localhost:11211', namespace: 'myapp', namespace_separator: '/')If you want to see the tracing path, the README says to add the OpenTelemetry gems to the Gemfile and Dalli instruments operations without further configuration:
# Gemfile
gem 'opentelemetry-sdk'
gem 'opentelemetry-exporter-otlp' # or your preferred exporterThe README states that when OpenTelemetry is loaded, Dalli creates spans for single-key operations such as get, set, delete, add, replace, incr and decr, for multi-key operations such as get_multi, set_multi and delete_multi, and for get_with_metadata and fetch_with_lock. If the SDK is absent, the README says there is zero overhead because the check runs once at startup.
The memcached version floor is a hard stop, not a warning
Dalli requires Ruby 3.3 or later, with JRuby also supported, and memcached 1.6.27 or later. The second requirement is the one that bites. The README explains why: earlier 1.6.x servers are not supported because the meta protocol rejects unknown flags outright, so features added after a server's release fail with CLIENT_ERROR invalid flag rather than degrading.
That is a different failure mode from the usual client-server mismatch. A client that degrades would let an unsupported option be ignored and the cache call still succeed. Here the operation errors. If your infrastructure runs a distribution-packaged memcached older than 1.6.27, upgrading Dalli is not a gem bump, it is a server upgrade first. The README does not document rollback, so the downgrade path is not something you can plan from the README alone.
The second limitation is the serializer default already described. Marshal round-trips Ruby objects, which is convenient, and it executes code on deserialization, which is dangerous when the cached bytes are attacker-influenced. A team caching rendered fragments or session-adjacent data has to decide whether that data is truly trusted. The README offers JSON as the alternative; it does not claim JSON preserves the same object types.
Dalli versus a connection-pooling wrapper approach
The obvious comparison is with clients that take the opposite threading stance. Dalli supports thread-safe operation in two ways: through a connection pool, or by using the client in threadsafe mode. A team already running a pool library can keep that structure and treat Dalli as the thing inside the pool.
The difference in approach is where the concurrency logic lives. In the pool model, the pool owns checkout, sizing and reuse, and the client is a relatively thin object. In Dalli's threadsafe mode, the client itself carries that responsibility. Which one fits depends on whether you already have pool instrumentation and tuning in place. A team with an established pool and metrics around it gains little from moving that concern into the cache client, and a team with no pool gets a working threaded setup without adding a dependency.
The tracing story is a separate axis. Dalli instruments itself when the OpenTelemetry SDK is present and emits attributes such as db.system set to memcached, db.operation with the operation name, and for multi-key calls db.memcached.key_count, db.memcached.hit_count and db.memcached.miss_count. Those hit and miss counts are the useful part: they tell you whether a get_multi call is actually saving round trips or just returning nils. Instrumentation can be turned off at runtime with Dalli::Instrumentation.disable!, or pointed at a custom tracer, which is what you want in a test suite where spans are noise.
Maintenance, upgrades and the MIT licence
The repository is not archived, and the last push was on 2026-08-16, the same date as the v5.1.0 release. The prior release, v5.0.6, landed on 2026-08-02. That is a recent cadence, and the presence of 3.0-Upgrade.md, 4.0-Upgrade.md and 5.0-Upgrade.md in the repository root shows the project documents breaking changes per major version rather than leaving them to the changelog alone.
The upgrade cost is concentrated in two places. First, the Ruby and memcached floors, which move with major versions and are stated in the README rather than discovered at runtime. Second, the serializer default, which the README flags in a dedicated security note and ties to the 5.0 upgrade guide. Any major-version jump should be read against those two documents before the Gemfile is changed.
Dalli is MIT licensed. That is permissive, and it means the licence itself rarely blocks adoption. The practical licence-adjacent question is not the gem's licence but the data you put in the cache and how it is serialized, since Marshal deserialization of untrusted input is the risk the README calls out. Nothing here is legal advice; the point is that the constraint is operational, not contractual.
Editorial conclusion
Adopt Dalli if you run Ruby 3.3 or later against memcached 1.6.27 or later and want a client that handles failover, namespaces and optional OpenTelemetry tracing without a native extension. Do not adopt it if you are pinned to an older 1.6.x memcached, because the README states the meta protocol rejects unknown flags with CLIENT_ERROR invalid flag instead of degrading, or if you cache user-controlled values and cannot switch the serializer away from Marshal. Before rolling it out, verify three things: your memcached version, whether any cached value originates from user input, and whether the wiki covers the failover behaviour you expect, since the README does not document rollback.
Frequently asked questions
What is Dalli?
Dalli is a pure Ruby client for accessing memcached servers, maintained by Peter M. Goldstein with Mike Perham as the original author. It supports failover, namespaces, SSL/TLS connections and OpenTelemetry tracing.
What Ruby and memcached versions does Dalli require?
The README states Ruby 3.3 or later, with JRuby also supported, and memcached 1.6.27 or later. Earlier 1.6.x servers are not supported.
Why does Dalli fail with CLIENT_ERROR invalid flag?
The README explains that the meta protocol rejects unknown flags outright, so features added after an older server's release fail with that error rather than degrading. The fix is upgrading memcached to 1.6.27 or later.
Is Dalli safe to use with user-controlled data?
Not with its default serializer. The README's security note states that Dalli uses Ruby's Marshal by default and that deserializing untrusted data with Marshal can lead to remote code execution, and suggests serializer: JSON for user-controlled values.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/petergoldstein-dalli)