{"id":13878201,"url":"https://github.com/pawurb/rails-brotli-cache","last_synced_at":"2025-05-16T18:05:33.271Z","repository":{"id":163386965,"uuid":"638688723","full_name":"pawurb/rails-brotli-cache","owner":"pawurb","description":"Drop-in enhancement for Rails cache, offering better performance and compression with Brotli algorithm","archived":false,"fork":false,"pushed_at":"2024-09-25T07:21:48.000Z","size":259,"stargazers_count":255,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-16T18:03:50.590Z","etag":null,"topics":["cache","performance","rails","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pawurb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-09T22:25:08.000Z","updated_at":"2025-04-16T11:49:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"6e17b337-cdf2-4f86-ae65-8b1c8560bb62","html_url":"https://github.com/pawurb/rails-brotli-cache","commit_stats":null,"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pawurb%2Frails-brotli-cache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pawurb%2Frails-brotli-cache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pawurb%2Frails-brotli-cache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pawurb%2Frails-brotli-cache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pawurb","download_url":"https://codeload.github.com/pawurb/rails-brotli-cache/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254582903,"owners_count":22095518,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","performance","rails","ruby"],"created_at":"2024-08-06T08:01:42.549Z","updated_at":"2025-05-16T18:05:33.226Z","avatar_url":"https://github.com/pawurb.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# Rails Brotli Cache [![Gem Version](https://img.shields.io/gem/v/rails-brotli-cache)](https://badge.fury.io/rb/rails-brotli-cache) [![GH Actions](https://github.com/pawurb/rails-brotli-cache/actions/workflows/ci.yml/badge.svg)](https://github.com/pawurb/rails-brotli-cache/actions)\n\nThis gem enables support for compressing Ruby on Rails cache entries using the [Brotli compression algorithm](https://github.com/google/brotli). `RailsBrotliCache::Store` offers better compression and performance compared to the default `Rails.cache` Gzip, regardless of the underlying data store. The gem also allows specifying any custom compression algorithm instead of Brotli.\n\nYou can check out [this blog post](https://pawelurbanek.com/rails-brotli-cache) describing the gem in more detail.\n\n## Installation\n\n`Gemfile`\n\n```ruby\n  gem 'brotli' # an optional dependency, other compressors are supported\n  gem 'rails-brotli-cache'\n```\n\n## Benchmarks\n\nBrotli cache works as a proxy layer wrapping the standard cache data store. It applies Brotli compression instead of the default Gzip before storing cache entries.\n\n```ruby\nredis_cache = ActiveSupport::Cache::RedisCacheStore.new(\n  url: \"redis://localhost:6379\"\n)\nbrotli_redis_cache = RailsBrotliCache::Store.new(redis_cache)\n```\n\n**~25%** better compression of a sample JSON object:\n\n```ruby\njson = File.read(\"sample.json\") # sample 435kb JSON text\njson.size # =\u003e 435662\nredis_cache.write(\"json\", json)\nbrotli_redis_cache.write(\"json\", json)\n\n## Check the size of cache entries stored in Redis\nredis = Redis.new(url: \"redis://localhost:6379\")\nredis.get(\"json\").size # =\u003e 31698 ~31kb\nredis.get(\"br-json\").size # =\u003e 24058 ~24kb\n```\n\n**~20%** better compression of a sample ActiveRecord objects array:\n\n```ruby\nusers = User.limit(100).to_a # 100 ActiveRecord objects\nredis_cache.write(\"users\", users)\nbrotli_redis_cache.write(\"users\", users)\n\nredis.get(\"users\").size # =\u003e 12331 ~12kb\nredis.get(\"br-users\").size # =\u003e 10299 ~10kb\n```\n\n**~25%** faster performance for reading/writing a larger JSON file:\n\n```ruby\njson = File.read(\"sample.json\") # sample ~1mb JSON text\n\nBenchmark.bm do |x|\n  x.report(\"redis_cache\") do\n    100.times do\n      redis_cache.write(\"test\", json)\n      redis_cache.read(\"test\")\n    end\n  end\n\n  x.report(\"brotli_redis_cache\") do\n    100.times do\n      brotli_redis_cache.write(\"test\", json)\n      brotli_redis_cache.read(\"test\")\n    end\n  end\n\n  # ...\nend\n\n# redis_cache  1.782225   0.049936   1.832161 (  2.523317)\n# brotli_redis_cache  1.218365   0.051084   1.269449 (  1.850894)\n# memcached_cache  1.766268   0.045351   1.811619 (  2.504233)\n# brotli_memcached_cache  1.194646   0.051750   1.246396 (  1.752982)\n# file_cache  1.727967   0.071138   1.799105 (  1.799229)\n# brotli_file_cache  1.128514   0.044308   1.172822 (  1.172983)\n```\n\nRegardless of the underlying data store, Brotli cache offers 20%-40% performance improvement.\n\nYou can run the benchmarks by executing:\n\n```ruby\ncp docker-compose.yml.sample docker-compose.yml\ndocker compose up -d\ncd benchmarks\nbundle install\nbundle exec ruby main.rb\n```\n\n## Configuration\n\nGem works as a drop-in replacement for a standard Rails cache store. You can configure it with different store types:\n\n```ruby\nconfig.cache_store = RailsBrotliCache::Store.new(\n  ActiveSupport::Cache::RedisCacheStore.new(url: \"redis://localhost:6379\")\n)\n```\n\n```ruby\nconfig.cache_store = RailsBrotliCache::Store.new(\n  ActiveSupport::Cache::MemCacheStore.new(\"localhost:11211\")\n)\n```\n\n```ruby\nconfig.cache_store = RailsBrotliCache::Store.new(\n  ActiveSupport::Cache::FileStore.new('/tmp')\n)\n```\n\nYou should avoid using it with `ActiveSupport::Cache::MemoryStore`. This type of cache store does not serialize or compress objects but keeps them directly in the RAM. In this case, adding this gem would reduce RAM usage but add huge performance overhead.\n\nGem appends `br-` to the cache key names to prevent conflicts with previously saved entries. You can disable this behavior by passing `{ prefix: nil }` during initialization:\n\n```ruby\nconfig.cache_store = RailsBrotliCache::Store.new(\n  ActiveSupport::Cache::RedisCacheStore.new,\n  { prefix: nil }\n)\n```\n\nAddition of the prefix means that you can safely add the Brotli the cache config and avoid compression algorithm conflicts between old and new entries. After configuring the Brotli cache you should run `Rails.cache.clear` to remove the outdated (gzipped) entries.\n\n### Use a custom compressor class\n\nBy default gem uses a Brotli compression, but you can customize the algorithm. You can pass a `compressor_class` object as a store configuration argument or directly to `read/write/fetch` methods:\n\n```ruby\nconfig.cache_store = RailsBrotliCache::Store.new(\n  ActiveSupport::Cache::RedisCacheStore.new,\n  { compressor_class: ZSTDCompressor }\n)\n```\n\n```ruby\n\nclass ZSTDCompressor\n  def self.deflate(payload)\n    ::Zstd.compress(payload, level: 10)\n  end\n\n  def self.inflate(payload)\n    ::Zstd.decompress(payload)\n  end\nend\n\nRails.cache.write('test-key', json, compressor_class: ZSTDCompressor)\n```\n\nThis config expects a class that defines two methods, `inflate` and `deflate`. It allows to use, for example, a [ZSTD by Facebook](https://github.com/SpringMT/zstd-ruby), offering even better performance and compression.\n\n## Testing\n\n```bash\ncp docker-compose.yml.sample docker-compose.yml\ndocker compose up -d\nrake test_all\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpawurb%2Frails-brotli-cache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpawurb%2Frails-brotli-cache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpawurb%2Frails-brotli-cache/lists"}