35+ Years Experience Netherlands Based ⚡ Fast Response Times Ruby on Rails Experts AI-Powered Development Fixed Pricing Available Senior Architects Dutch & English 35+ Years Experience Netherlands Based ⚡ Fast Response Times Ruby on Rails Experts AI-Powered Development Fixed Pricing Available Senior Architects Dutch & English

Rails 8 Solid Cable: WebSockets Zonder Redis — Eén Dependency Minder

TTB Software
rails, devops
Solid Cable instellen in Rails 8 voor Action Cable via SQLite of PostgreSQL. Configuratie, prestaties, migratie vanaf Redis, en wanneer je Redis toch wilt houden.

Rails 8 levert Solid Cable standaard mee als Action Cable adapter voor nieuwe applicaties. Als je Redis alleen draaide voor WebSocket-broadcasts, kun je die dependency nu volledig verwijderen. Je database handelt het af.

Hier lees je hoe je het instelt, wat de prestaties zijn in productie, en waar de grenzen liggen.

Wat Solid Cable Precies Is

Solid Cable is een database-backed adapter voor Action Cable. In plaats van berichten via Redis pub/sub te publiceren, schrijft het broadcast-berichten naar een databasetabel en pollt het voor nieuwe berichten. Het wordt geleverd als de solid_cable gem, standaard inbegrepen in Rails 8.0+.

Het verschil met Redis: Solid Cable gebruikt polling in plaats van pub/sub. Een achtergrondthread controleert de database op nieuwe berichten met een instelbaar interval (standaard: 0.1 seconden). Dat klinkt alsof het trager zou moeten zijn, en technisch is dat ook zo — maar voor de overgrote meerderheid van applicaties merkt geen gebruiker het verschil.

Stel het je zo voor: als je chatbericht in 100ms aankomt in plaats van 5ms, merkt niemand dat. Als het verwijderen van Redis je een managed instance van €15/maand bespaart en één ding minder om 3 uur ‘s nachts te monitoren, merkt iedereen dat.

Solid Cable Instellen in een Nieuwe Rails 8 App

Nieuwe Rails 8 apps krijgen Solid Cable standaard geconfigureerd. Start rails new myapp en bekijk config/cable.yml:

development:
  adapter: solid_cable
  silence_polling: true

test:
  adapter: test

production:
  adapter: solid_cable
  connects_to:
    database:
      writing: cable
  polling_interval: 0.1.seconds

Het connects_to-blok wijst Solid Cable naar een aparte database. Rails 8 configureert standaard een apart SQLite-database voor cable in config/database.yml:

production:
  primary:
    <<: *default
    database: storage/production.sqlite3
  cable:
    <<: *default
    database: storage/production_cable.sqlite3
    migrations_paths: db/cable_migrate

Voer de installer uit als het niet automatisch was geconfigureerd:

bin/rails solid_cable:install

Dit genereert de migratie voor de solid_cable_messages tabel en werkt je configuratiebestanden bij.

Migreren van Redis naar Solid Cable

Als je Rails 7 of een vroege Rails 8 app draait met Redis als cable adapter, is dit het migratiepad.

Stap 1: Voeg de gem toe

# Gemfile
gem "solid_cable"
bundle install
bin/rails solid_cable:install

Stap 2: Voer de migratie uit

bin/rails db:migrate

De migratie maakt één tabel aan:

create_table :solid_cable_messages do |t|
  t.text :channel, null: false
  t.text :payload, null: false, limit: 536870912
  t.datetime :created_at, null: false
  t.index [:channel, :created_at]
  t.index :created_at
end

Stap 3: Werk cable.yml bij

Vervang je Redis-configuratie:

# Voorheen
production:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL", "redis://localhost:6379/1") %>

# Nu
production:
  adapter: solid_cable
  connects_to:
    database:
      writing: cable
  polling_interval: 0.1.seconds

Stap 4: Configureer de aparte database

Voeg een cable database-entry toe aan config/database.yml. Voor PostgreSQL:

production:
  primary:
    <<: *default
    database: myapp_production
  cable:
    <<: *default
    database: myapp_production_cable
    migrations_paths: db/cable_migrate

Stap 5: Deploy en verifieer

Na het deployen van je Rails 8 app, controleer de logs op SolidCable initialisatieberichten. Open een browserconsole op een pagina met een actieve WebSocket-verbinding en bevestig dat berichten doorstromen.

Als alles werkt, kun je de redis gem uit je Gemfile verwijderen (mits niets anders het gebruikt — controleer eerst je achtergrondtaken-setup en caching-configuratie).

Prestaties: Wat Je Kunt Verwachten

Ik heb Solid Cable gedraaid op een productie-app met ~200 gelijktijdige WebSocket-verbindingen en ongeveer 50 broadcasts per seconde. De setup: een enkele PostgreSQL 15 instantie op een 2-vCPU server met 4GB RAM.

Resultaten:

  • Berichtlatentie: 95e percentiel op 85ms (vs ~12ms met Redis op dezelfde hardware)
  • Databasebelasting: De polling-queries voegden ~3% CPU-gebruik toe aan de PostgreSQL-instantie
  • Geheugen: Elimineerde ~60MB aan Redis-geheugengebruik
  • Tabelgrootte: Met de standaard message_retention van 5 minuten bleef de tabel onder de 2.000 rijen

Het latentieverschil is reëel maar irrelevant voor de meeste use cases. Notificatiesystemen, live dashboards, chatfuncties in zakelijke apps, cursors voor collaborative editing — ze werken allemaal prima met sub-100ms levering.

Waar het begint uit te maken: high-frequency trading dashboards, multiplayer game state synchronisatie, of elk scenario met honderden berichten per seconde naar duizenden clients. Daarvoor houd je Redis.

Configuratie-opties Die Ertoe Doen

Solid Cable heeft een paar knoppen die de moeite waard zijn:

production:
  adapter: solid_cable
  connects_to:
    database:
      writing: cable
  polling_interval: 0.1.seconds
  message_retention: 5.minutes
  autotrim: true

polling_interval — Hoe vaak Solid Cable controleert op nieuwe berichten. De standaard van 0.1 seconden (100ms) is een goede balans. Lager verhoogt de databasebelasting. Hoger verhoogt de latentie. Ik zou niet onder 0.05 seconden gaan tenzij je je database hebt gebenchmarkt.

message_retention — Hoe lang berichten in de tabel blijven voor ze worden opgeruimd. De standaard van 5 minuten is ruim. Als je WebSocket-verbindingen stabiel zijn en berichten snel worden geconsumeerd, kun je dit naar 1 minuut verlagen.

autotrim — Verwijdert automatisch verlopen berichten. Laat dit aan. Zonder groeit je berichtentabel oneindig en worden de polling-queries trager.

Aparte Database (en Waarom Je Dat Wilt)

Solid Cable werkt prima op je primaire database. Maar een aparte database is beter om twee redenen:

  1. Isolatie: Polling-queries concurreren niet met je applicatie-queries om connection pool slots of I/O-bandbreedte
  2. Opruimen: Het trimmen van oude berichten veroorzaakt writes en mogelijke table bloat. Op een aparte database raakt dit je primaire data niet.

Voor SQLite-deployments (single-server setups) is de aparte database vrijwel gratis — het is gewoon een extra bestand. Voor PostgreSQL betekent het een extra logische database op dezelfde server, wat bijna niets kost.

Als je ook Solid Queue draait voor achtergrondtaken, vraag je je misschien af of je een database kunt delen tussen Solid Cable en Solid Queue. Niet doen. Hun toegangspatronen zijn anders — Solid Queue doet veel row locking, Solid Cable doet veel sequential scans. Houd ze gescheiden.

Het Trim-probleem op Drukke Systemen

Iets wat de docs onvoldoende benadrukken: op high-throughput systemen kan de autotrim af en toe lock contention veroorzaken. De trim-operatie voert een DELETE FROM solid_cable_messages WHERE created_at < ? query uit, die op PostgreSQL row-level locks verwerft.

Als je PG::LockNotAvailable fouten ziet in je logs tijdens drukke broadcast-periodes, heb je twee opties:

  1. Trim minder frequent door message_retention te verhogen
  2. Plan een scheduled job voor trimmen in rustigere periodes:
# app/jobs/trim_cable_messages_job.rb
class TrimCableMessagesJob < ApplicationJob
  queue_as :maintenance

  def perform
    SolidCable::Message.where("created_at < ?", 5.minutes.ago)
                        .in_batches(of: 1000)
                        .delete_all
  end
end

Schakel dan autotrim uit in de config en plan deze job in tijdens rustigere momenten.

Multi-Server Deployments

Solid Cable werkt over meerdere app-servers zolang ze allemaal verbinden met dezelfde cable-database. Dat is het hele punt van een database-adapter — gedeelde state zonder een apart service.

Met Redis moest elke server verbinden met dezelfde Redis-instantie. Met Solid Cable moet elke server verbinden met dezelfde cable-database. De operationele complexiteit is vergelijkbaar, maar je hebt één service minder draaien.

Eén kanttekening: als je SQLite gebruikt als cable-database, werkt multi-server niet (SQLite ondersteunt geen gelijktijdige toegang van meerdere machines). Gebruik PostgreSQL of MySQL voor multi-server setups.

Wanneer Je Redis Houdt

Solid Cable is niet overal de juiste keuze. Houd Redis voor Action Cable als:

  • Je consistent meer dan 500 berichten per seconde broadcast
  • Sub-10ms berichtlatentie een zakelijke vereiste is
  • Je Redis al draait voor caching of achtergrondtaken en de operationele overhead al betaald is
  • Je een cluster van 10+ app-servers draait (de polling-belasting schaalt lineair met het aantal servers)

Het omslagpunt in mijn ervaring: als Redis er alleen is voor Action Cable, verwijder het. Als Redis drie doelen dient en je het toch zou houden, maakt de adapterkeuze minder uit.

FAQ

Kan Solid Cable duizenden gelijktijdige WebSocket-verbindingen aan?

Ja, maar de bottleneck is niet de adapter — het is het vermogen van je app-server om open verbindingen vast te houden. Een enkel Puma-proces met 5 threads kan ongeveer 1.000 WebSocket-verbindingen aan voordat geheugen de beperkende factor wordt. Solid Cable’s polling is lichtgewicht ongeacht het aantal verbindingen, omdat het per channel queryt, niet per verbinding.

Werkt Solid Cable met Turbo Streams?

Solid Cable is volledig compatibel met Turbo Streams. Turbo Streams gebruiken Action Cable onder de motorkap, en Solid Cable is een drop-in adapter-vervanging. Je turbo_stream_from helpers, broadcasts_to callbacks en Turbo::StreamsChannel subscriptions werken ongewijzigd.

Wat gebeurt er als de cable-database uitvalt?

WebSocket-verbindingen blijven open maar stoppen met het ontvangen van broadcasts. Zodra de database herstelt, hervat polling en worden berichten die tijdens de storing zijn geschreven (door servers die nog konden schrijven) bezorgd als ze binnen het retentievenster vallen. Clients disconnecten niet — ze stoppen tijdelijk met het ontvangen van updates.

Moet ik SQLite of PostgreSQL gebruiken voor de cable-database?

SQLite is prima voor single-server deployments en houdt het simpel. PostgreSQL is nodig voor multi-server setups. De prestaties zijn vergelijkbaar voor typische broadcast-volumes (onder 100 berichten/seconde). Als je PostgreSQL al draait als primaire database, gebruik het dan ook voor cable — één database-engine minder om over na te denken.

Is Solid Cable productie-klaar?

Het werd geleverd als de standaard in Rails 8.0 en is stabiel sinds de 1.0 release. Basecamp en HEY (37signals apps) gebruiken de Solid-familie van libraries in productie. Het is niet experimenteel — het is het beoogde pad voorwaarts voor Rails-applicaties die geen Redis-niveau throughput nodig hebben.

T

About the Author

Roger Heykoop is een senior Ruby on Rails ontwikkelaar met 19+ jaar Rails ervaring en 35+ jaar ervaring in softwareontwikkeling. Hij is gespecialiseerd in Rails modernisering, performance optimalisatie, en AI-ondersteunde ontwikkeling.

Get in Touch

Share this article

Need Expert Rails Development?

Let's discuss how we can help you build or modernize your Rails application with 19+ years of expertise

Schedule a Free Consultation