RepoPilotOpen in app →

petergoldstein/dalli

High performance memcached client for Ruby

Healthy

Healthy across all four use cases

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 3w ago
  • 8 active contributors
  • MIT licensed
Show 3 more →
  • CI configured
  • Tests present
  • Single-maintainer risk — top contributor 84% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/petergoldstein/dalli)](https://repopilot.app/r/petergoldstein/dalli)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/petergoldstein/dalli on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: petergoldstein/dalli

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/petergoldstein/dalli shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • Last commit 3w ago
  • 8 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Single-maintainer risk — top contributor 84% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live petergoldstein/dalli repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/petergoldstein/dalli.

What it runs against: a local clone of petergoldstein/dalli — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in petergoldstein/dalli | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | Last commit ≤ 49 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>petergoldstein/dalli</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of petergoldstein/dalli. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/petergoldstein/dalli.git
#   cd dalli
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of petergoldstein/dalli and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "petergoldstein/dalli(\\.git)?\\b" \\
  && ok "origin remote is petergoldstein/dalli" \\
  || miss "origin remote is not petergoldstein/dalli (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 49 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~19d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/petergoldstein/dalli"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Dalli is a high-performance pure Ruby memcached client that handles distributed caching across multiple memcached servers (1.6+). It provides automatic failover, sophisticated serialization/compression control, thread-safe operation via connection pooling, and built-in OpenTelemetry tracing without explicit configuration. Single-package structure: lib/dalli/ is the core library with protocol implementations (lib/dalli/protocol/base.rb, lib/dalli/protocol/meta.rb), client abstractions (lib/dalli/client.rb, lib/dalli/cas/client.rb), helper modules (key_manager.rb, compressor.rb, instrumentation.rb), and pipelined operation handlers (pipelined_getter.rb, pipelined_setter.rb, pipelined_deleter.rb). Instrumentation hooks throughout for OpenTelemetry integration.

👥Who it's for

Ruby/Rails developers building high-traffic web applications who need a production-grade caching layer. DevOps engineers maintaining memcached infrastructure want reliable client libraries. Gem maintainers and framework developers integrate Dalli to provide caching abstractions to their users.

🌱Maturity & risk

Highly mature and actively maintained. The codebase is 426KB of Ruby with well-established patterns (5.0 upgrade guide exists), comprehensive CI via GitHub Actions (tests, benchmarks, CodeQL), and organized changelog documenting breaking changes across major versions. This is production-ready software used in large Rails applications.

Low risk overall. Single primary maintainer (petergoldstein) creates a potential bus factor, but the project has stable semantics and good test coverage via the CI pipeline. Recent activity visible in workflows and upgrade guides shows ongoing maintenance. Breaking changes are rare and well-documented (3.0, 4.0, 5.0 upgrade guides). No evidence of large unresolved security issues based on file structure.

Active areas of work

Active development on observability and protocol compliance. OpenTelemetry instrumentation is built-in with automatic span creation for operations. CodeQL security analysis runs on every push. Performance benchmarking and profiling tools are maintained in bin/. The project maintains compatibility with Ruby 3.3+ and JRuby while keeping memcached protocol current.

🚀Get running

Clone and use the devcontainer setup: git clone https://github.com/petergoldstein/dalli.git && cd dalli && .devcontainer/setup.sh. Or manually: bundle install && bin/setup. For development: bundle exec rake test to run the full test suite against local or Docker memcached. Docker Compose is configured in .devcontainer/docker-compose.yml for isolated testing.

Daily commands: Development: bundle install && bin/console opens an IRB session with Dalli loaded. Testing: bundle exec rake test runs RSpec tests. Benchmarking: bin/benchmark compares performance, bin/profile generates CPU/memory profiles, bin/benchmark_branch compares branches. All assume a local memcached server running on localhost:11211 or one spun up via Docker.

🗺️Map of the codebase

  • lib/dalli/client.rb: Main public API: defines Dalli::Client class with get, set, delete, get_multi, set_multi, CAS operations. Entry point for 90% of user code.
  • lib/dalli/protocol/base.rb: Low-level memcached binary protocol implementation: handles socket communication, request/response serialization, and connection state management.
  • lib/dalli/protocol/connection_manager.rb: Manages connection pooling, failover logic between multiple memcached servers, and thread-safe connection distribution.
  • lib/dalli/instrumentation.rb: OpenTelemetry integration hooks: automatically creates spans for cache operations when OpenTelemetry SDK is present. No configuration needed.
  • lib/dalli/pipelined_getter.rb: Optimizes multi-key reads (get_multi) by batching requests into single round-trips to memcached servers.
  • lib/dalli/cas/client.rb: Compare-and-swap (CAS) operations for atomic updates: extends base Client with cas() and fetch_with_lock() methods for optimistic locking patterns.
  • lib/dalli/options.rb: Unified options parsing and validation for all Dalli::Client configuration parameters (namespace, serializer, compressor, ssl, etc).

🛠️How to make changes

Protocol changes go in lib/dalli/protocol/. Client API extensions in lib/dalli/client.rb. Instrumentation hooks in lib/dalli/instrumentation.rb. Serialization logic in lib/dalli/compressor.rb and options parsing in lib/dalli/options.rb. Key transformation in lib/dalli/key_manager.rb. Tests live in parallel structure under test/. Use Rubocop for style (.rubocop.yml configured) and Standard for linting.

🪤Traps & gotchas

Memcached server must be running on specified host:port before client operations (defaults to localhost:11211). If using namespace with dynamic Proc, the Proc is evaluated on every operation, potentially creating performance bottlenecks if expensive. Marshal serializer deserializes untrusted data by default—security risk if caching user-controlled content; must explicitly set serializer: JSON. SSL/TLS requires memcached compiled with TLS support (not all distributions include this). Thread-safety requires either connection pooling or explicit threadsafe mode; raw client instance is not inherently thread-safe. Key size limited to 250 bytes by memcached protocol; Dalli's key manager handles normalization but doesn't validate input key length.

💡Concepts to learn

  • Memcached Binary Protocol — Dalli implements the full binary protocol (not text protocol) for correctness and performance; understanding request/response framing, command opcodes, and flags is essential for debugging and extending Dalli's protocol layer in lib/dalli/protocol/base.rb.
  • Compare-and-Swap (CAS) — Dalli provides CAS operations via lib/dalli/cas/client.rb for atomic updates without locks; this is a critical pattern for distributed caching where multiple clients might update the same key simultaneously.
  • Connection Pooling with Failover — Dalli's lib/dalli/protocol/connection_manager.rb manages multiple memcached server connections with automatic failover; understanding consistent hashing and health detection is needed to modify caching topology behavior.
  • Request Pipelining — Multi-key operations (get_multi, set_multi) in lib/dalli/pipelined_getter.rb and lib/dalli/pipelined_setter.rb batch requests to reduce round-trip latency; critical for performance optimization in high-volume scenarios.
  • Consistent Hashing — When distributing keys across multiple memcached servers, Dalli uses consistent hashing to minimize key remapping when servers are added/removed; essential for understanding failover behavior in lib/dalli/protocol/connection_manager.rb.
  • Serialization Pluggability — Dalli's default Marshal serializer is configurable (JSON, MessagePack, etc.) via lib/dalli/compressor.rb; security-critical for applications caching untrusted user data due to Marshal deserialization RCE risks.
  • OpenTelemetry Auto-Instrumentation — Dalli automatically creates observability spans (lib/dalli/instrumentation.rb) when OpenTelemetry SDK is loaded without explicit user configuration; understanding this pattern is needed for maintaining/extending tracing in Dalli.
  • memcached/memcached — The server implementation that Dalli communicates with; understanding memcached protocol and commands is essential for contributing to Dalli.
  • redis/redis-rb — Alternative Ruby caching client for Redis instead of memcached; similar design patterns (connection pooling, pipelining, instrumentation) but different underlying protocol.
  • ruby-rails/rails — Rails integrates Dalli as the default memcached adapter for ActionController::Caching; Dalli must maintain API stability with Rails' cache store interface.
  • open-telemetry/opentelemetry-ruby — OpenTelemetry Ruby SDK that Dalli auto-instruments against; Dalli's instrumentation.rb depends on this library being present for tracing.
  • brynary/memcache-client — Historical predecessor Ruby memcached client; Dalli was built as a modern replacement with better performance and protocol compliance.

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive test coverage for lib/dalli/protocol/meta.rb

The META protocol is a newer memcached protocol that offers better performance. While the file exists at lib/dalli/protocol/meta.rb, there's no evidence of dedicated test file (test/unit/protocol/meta_test.rb or similar). Given the complexity of protocol parsing and the importance of correctness for a memcached client, this protocol implementation needs thorough unit tests covering edge cases, malformed responses, and all command types.

  • [ ] Create test/unit/protocol/meta_test.rb with tests for response parsing
  • [ ] Add tests for request formatting with various flags and options
  • [ ] Test error handling and malformed response scenarios
  • [ ] Add integration tests in test/ directory for META protocol operations (get, set, delete, cas, etc.)
  • [ ] Verify coverage of all response types (SUCCESS, NOT_FOUND, EXISTS, NOT_STORED, etc.)

Add SSL/TLS connection tests and CI workflow validation

The README advertises 'SSL/TLS connections to memcached' support via lib/dalli/socket.rb, but there's no dedicated GitHub Actions workflow to validate SSL/TLS functionality (.github/workflows/tests.yml doesn't appear to test this). This is a critical security feature that needs continuous validation. Add a CI workflow that tests against a memcached instance with SSL/TLS enabled.

  • [ ] Create .github/workflows/ssl-tests.yml that sets up memcached with TLS certificates
  • [ ] Add test fixtures (certificates/keys) in test/fixtures/ssl/
  • [ ] Create test/unit/ssl_test.rb with tests for SSL connection, certificate validation, and error cases
  • [ ] Test both successful SSL connections and failure scenarios (bad cert, wrong port, etc.)
  • [ ] Document SSL testing setup in .devcontainer/setup.sh or similar

Add instrumentation/observability tests for lib/dalli/instrumentation.rb

The file lib/dalli/instrumentation.rb exists and supports OpenTelemetry tracing (mentioned in README), but there are no visible test files validating this instrumentation layer. This is critical for users relying on distributed tracing. Add comprehensive tests ensuring all cache operations emit correct instrumentation events with proper attributes.

  • [ ] Create test/unit/instrumentation_test.rb to test ActiveSupport::Notifications event emission
  • [ ] Add tests for OpenTelemetry span creation and attributes for get, set, delete, and cas operations
  • [ ] Test instrumentation error handling (span error tagging, exception reporting)
  • [ ] Add integration test in test/ validating end-to-end tracing with mock OpenTelemetry SDK
  • [ ] Document instrumentation configuration in CONTRIBUTING.md or a new INSTRUMENTATION.md file

🌿Good first issues

  • Add comprehensive test coverage for lib/dalli/key_manager.rb edge cases around namespace separator validation and dynamic namespace evaluation. Currently no dedicated test file visible in the structure.
  • Document SSL/TLS setup examples in README.md or new docs file, including how to verify memcached supports TLS and certificate configuration. Currently only mentioned in upgrade guides.
  • Add type hints / YARD documentation to lib/dalli/protocol/request_formatter.rb and lib/dalli/protocol/key_regularizer.rb—these are low-level utilities that contributors frequently need to understand but lack inline documentation.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 9d5fef6 — Merge pull request #1095 from petergoldstein/chore/fix-rubocop-redundant-disable (petergoldstein)
  • 5139d8b — Fix assert_raises message: keyword incompatibility with Minitest 6 (petergoldstein)
  • 79b3070 — Remove redundant rubocop disable directive in test/helper.rb (petergoldstein)
  • f3e1af4 — Merge pull request #1094 from petergoldstein/chore/changelog-1093 (petergoldstein)
  • f26c202 — Update CHANGELOG for #1093 (petergoldstein)
  • 39b67b4 — Merge pull request #1093 from sam-obeid/perform-eliminate-double-array-allocation (petergoldstein)
  • 7775e07 — Disable Naming/MethodParameterName cop for Client#perform (sam-obeid)
  • 5e082c1 — The private method perform was declared as perform(*all_args) and then immediately destructured the splat with (sam-obeid)
  • 69343bb — Merge pull request #1091 from petergoldstein/chore/consolidated-dependency-updates (petergoldstein)
  • 598b508 — Bump actions/upload-artifact from v6 to v7 (petergoldstein)

🔒Security observations

Dalli is a mature Ruby memcached client with generally sound architecture. The main security concerns are around unsafe deserialization practices (Ruby Marshal), input validation for memcached keys, and timing attack vulnerabilities in authentication. The codebase lacks comprehensive security documentation for SSL/TLS configuration and responsible disclosure procedures. No hardcoded credentials or SQL injection risks were identified. The project would benefit from enhanced input validation, security documentation, and security policy guidelines.

  • Medium · Potential Unsafe Serialization with Marshal — lib/dalli/protocol/value_marshaller.rb. The codebase includes lib/dalli/protocol/value_marshaller.rb which likely handles Ruby object serialization. Marshal.load() is known to be unsafe when deserializing untrusted data as it can execute arbitrary code. If memcached data can be influenced by untrusted sources, this poses a security risk. Fix: Review the marshalling implementation to ensure it validates data before deserialization. Consider using safer serialization formats like JSON for untrusted data, or implement strict allowlisting of permitted classes for deserialization.
  • Medium · Lack of Input Validation in Key Management — lib/dalli/key_manager.rb, lib/dalli/protocol/key_regularizer.rb. The key_manager.rb and key_regularizer.rb modules handle user-provided keys for memcached operations. Without proper validation, oversized keys, special characters, or malformed input could cause unexpected behavior or protocol violations. Fix: Implement strict input validation for memcached keys including length checks (max 250 bytes), character set validation, and sanitization. Add comprehensive unit tests for edge cases.
  • Medium · Potential Timing Attack in Authentication — lib/dalli (authentication implementation). The authentication module (test/integration/test_authentication.rb exists) may be vulnerable to timing attacks if password comparison is not constant-time. Timing differences during SASL authentication could leak information about valid credentials. Fix: Use constant-time comparison functions (e.g., ActiveSupport::SecurityUtils.secure_compare or OpenSSL::HMAC.compare_digest) for all credential/password comparisons.
  • Low · SSL/TLS Configuration Options Not Fully Documented — lib/dalli/socket.rb, README.md. While the README mentions SSL/TLS support, there are no visible security guidelines documenting required cipher suites, certificate validation, or protocol version requirements. Users might misconfigure insecure SSL settings. Fix: Add comprehensive security documentation for SSL/TLS configuration including recommended cipher suites, minimum TLS version (1.2+), and certificate validation best practices.
  • Low · Missing Security Headers in Development Container — .devcontainer/docker-compose.yml. The .devcontainer/docker-compose.yml may expose memcached ports (default 11211) without authentication if not properly configured. Development containers should implement network isolation. Fix: Ensure memcached in dev containers is only accessible on localhost, require SASL authentication, and document that production deployments must use firewall rules and authentication.
  • Low · No Security Policy Documentation — Repository root. There is no SECURITY.md file visible in the repository for responsible vulnerability disclosure. This makes it difficult for security researchers to report issues privately. Fix: Create a SECURITY.md file documenting vulnerability reporting procedures, security contact information, and responsible disclosure practices.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · petergoldstein/dalli — RepoPilot