0.0
The project is in a healthy, maintained state
Coalesce concurrent cache-miss computations with Redis-backed locks and shared results.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

>= 1.17
>= 13.0
~> 3.12
~> 0.22

Runtime

>= 4.0
 Project Readme

Cache Coalescer

Gem Version Gem Downloads Ruby CI GitHub Release Rails Elysium Arc

Distributed singleflight for Rails cache misses to prevent stampedes on cold keys.

About

Cache Coalescer ensures only one request computes a missing value while the rest wait for it. The first caller acquires a lock, computes, and writes to cache. Other callers poll briefly and reuse the result. Optional stale values can be served if the lock is held for too long.

This is ideal for expensive cache-miss work such as API calls, report generation, or heavyweight database queries.

Use Cases

  • Prevent thundering herds on cold cache keys
  • Reduce p99 latency spikes during traffic bursts
  • Protect downstream services from request stampedes
  • Coalesce expensive fan-out workloads into a single computation

Compatibility

  • Ruby 3.0+
  • ActiveSupport 6.1+
  • Works with any ActiveSupport cache store
  • Best with Redis-backed stores for distributed locking

Elysium Arc Reliability Toolkit

Also check out these related gems:

Installation

# Gemfile

gem "cache-coalescer"

Usage

value = Cache::Coalescer.fetch("expensive-key", ttl: 60, lock_ttl: 5, wait_timeout: 2, store: Rails.cache) do
  ExpensiveQuery.call
end

Rails integration adds Rails.cache.fetch_coalesced:

Rails.cache.fetch_coalesced("expensive-key", ttl: 60) { ExpensiveQuery.call }

Options

  • ttl (Integer) cache TTL in seconds
  • lock_ttl (Integer) lock expiry in seconds
  • wait_timeout (Float) how long waiters poll for a result
  • wait_sleep (Float) polling interval in seconds
  • stale_ttl (Integer) optional stale window; if set, stale values are returned on timeout
  • store ActiveSupport cache store (defaults to Rails.cache when available)
  • lock_client Redis client or Cache::Coalescer::Lock::InMemoryLock

Locking

If the cache store exposes redis, a Redis lock is used automatically. Otherwise, the gem falls back to an in-memory lock which is safe for single-process usage.

Release

bundle exec rake release