#solid cable 🇬🇧

Ruby on Rails solid cache, cable, queue with mulitple database on Heroku

Jeanro Krupa Jeanro Krupa

Jeanro Krupa

3 min read
Ruby on Rails solid cache, cable, queue with mulitple database on Heroku

Running Rails 8 Solid Cache, Queue & Cable on Heroku with Multiple Databases


Rails 8 ships with the Solid trifecta:

  • Solid Cache  durable, DB-backed cache store
  • Solid Queue  jobs without Redis
  • Solid Cable  Action Cable on Postgres

Together, they let you drop Redis entirely and run your whole stack on Postgres. Perfect for Heroku… but there are a few gotchas if you want to isolate each component into its own database.

This article shows how I set up Rails 8 + Heroku with:

  • Primary DB → app data + jobs (Solid Queue) + websockets (Solid Cable)
  • Cache DB → Solid Cache (kept separate to avoid bloat) (but you can run on 3 different DB)


Why multiple databases?

Solid’s docs suggest splitting out Cache/Queue/Cable into separate DBs. On Heroku you can start simple (1 DB for everything), but caches tend to churn. If you expect lots of API hits or domain-level caching, isolating Solid Cache is cheap insurance:

  • Primary stays lean → your schema/migrations aren’t slowed by millions of cache rows.
  • Cache is disposable → you can drop & recreate it without touching app data.
  • Scaling knobs → you can upgrade just the cache DB if needed.


Database.yml setup

Rails already wires up multi-DB. In production, switch to url: so Heroku env vars work:
production:
  primary:
    <<: *default
    url: <%= ENV["DATABASE_URL"] %>

  cache:
    <<: *default
    url: <%= ENV["CACHE_DATABASE_URL"] || ENV["DATABASE_URL"] %>
    migrations_paths: db/cache_migrate

  queue:
    <<: *default
    url: <%= ENV["DATABASE_URL"] %>
    migrations_paths: db/queue_migrate

  cable:
    <<: *default
    url: <%= ENV["DATABASE_URL"] %>
    migrations_paths: db/cable_migrate


Cache.yml

Rails tells Solid Cache which DB to use via config/cache.yml:
production:
  database: cache
  store_options:
    namespace: production
Don’t duplicate the config in production.rb. Just:
# config/environments/production.rb
config.cache_store = :solid_cache_store
That’s it. Solid will pick up the cache connection from cache.yml.


Installing the schemas

Solid creates db/cache_schema.rb, db/queue_schema.rb, db/cable_schema.rb.
Put each into its own migration folder:

  • db/cache_migrate/init_solid_cache.rb
  • db/queue_migrate/init_solid_queue.rb
  • db/cable_migrate/init_solid_cable.rb

Each migration just loads the schema:
class InitSolidCache < ActiveRecord::Migration[8.0]
  def up
    load Rails.root.join("db/cache_schema.rb")
  end
  def down = raise ActiveRecord::IrreversibleMigration
end
Rails knows which DB to run it against based on the folder.

Run once:
bin/rails db:migrate
All four DBs (primary + cache + queue + cable) will be created and seeded.


Heroku setup

Provision two Postgres add-ons:
heroku addons:create heroku-postgresql:essential-0   # primary
heroku addons:create heroku-postgresql:essential-0        # cache
Alias the second one:
heroku config:set CACHE_DATABASE_URL=$(heroku config:get HEROKU_POSTGRESQL_BLUE_URL)
Deploy + migrate:
git push heroku main
heroku run rails db:migrate


Smoke tests

Cache write/read in your heroku console
Rails.cache.write("smoke:key","ok",expires_in:60)
puts Rails.cache.read("smoke:key")

Queue enqueue:
ApplicationJob.perform_later("smoke")   # should see the job run (if SOLID_QUEUE_IN_PUMA=1)


Cleanup job (recommended)

Caches grow. Add a nightly cleanup to delete expired entries

Lessons learned

  • Don’t duplicate config: pick cache.yml or production.rb for Solid Cache, not both.
  • Each schema file lives in its own db/*_migrate folder → Rails handles connections.
  • Add test.cache/queue/cable entries in database.yml to avoid KeyErrors in dev.
  • Start with 1 DB if you’re unsure. Splitting out cache is a 5-minute change later.

Pricing
each DB costs 10$/month on Heroku so make sure you need it ;) 

Feed
Sign up or Sign in to comment
Icons/delimiter straight multiple %# Main fill %> %# Black border with increased stroke width %> %# Shadow effect - slightly offset path %>