Solid Queue en Solid Cache in Rails 8: Complete Gids voor Technische Sollicitatiegesprekken 2026

Diepgaande analyse van Solid Queue en Solid Cache, de database-backed standaardcomponenten in Rails 8. Job-batches, fiber-uitvoering, Active Job Continuations en interviewvoorbereiding voor 2026.

Architectuurdiagram van Solid Queue en Solid Cache in Rails 8

Solid Queue en Solid Cache vormen de meest ingrijpende infrastructuurwijziging in de geschiedenis van Rails. Beide componenten worden standaard meegeleverd in Rails 8 en vervangen Redis voor achtergrondtaken en caching door database-backed alternatieven die een complete laag van operationele complexiteit elimineren.

De Solid-driehoek

Rails 8 gebruikt standaard drie database-backed componenten: Solid Queue (achtergrondtaken), Solid Cache (cache-opslag) en Solid Cable (WebSockets). Samen verwijderen ze de Redis-afhankelijkheid voor de meeste Rails-applicaties. Dit is een veelvoorkomend onderwerp in technische interviews over Rails 8.

Hoe Solid Queue Redis-gebaseerde job-backends vervangt

Solid Queue is een database-backed Active Job-backend die taken rechtstreeks opslaat in PostgreSQL, MySQL of SQLite. Het kernmechanisme is FOR UPDATE SKIP LOCKED, een SQL-feature beschikbaar vanaf PostgreSQL 9.5+ en MySQL 8+ dat een reguliere databasetabel omzet in een concurrent job-wachtrij zonder blokkering.

De architectuur bestaat uit drie componenten:

  • Workers bevragen solid_queue_ready_executions en claimen taken met behulp van SKIP LOCKED
  • Dispatchers verplaatsen geplande taken van solid_queue_scheduled_executions naar de ready-tabel wanneer het uitvoeringstijdstip is bereikt
  • Schedulers beheren terugkerende taken die in de configuratie zijn gedefinieerd
ruby
# config/solid_queue.yml
production:
  dispatchers:
    - polling_interval: 1
      batch_size: 500
  workers:
    - queues: "*"
      threads: 5
      polling_interval: 0.1
      processes: 2

Deze configuratie start twee worker-processen met elk 5 threads, die elke 100 ms pollen. De dispatcher controleert geplande taken elke seconde in batches van 500.

Transactionele job-enqueueing in Rails 8

Een van de sterkste argumenten voor Solid Queue ten opzichte van Redis-gebaseerde backends is transactionele enqueueing. Wanneer een taak wordt ingepland binnen een databasetransactie, wordt deze pas zichtbaar na de commit van die transactie. Redis-gebaseerde backends kunnen deze garantie niet bieden: een taak kan worden uitgevoerd voordat de transactie die deze heeft aangemaakt is afgerond, waarbij wordt verwezen naar records die nog niet bestaan.

ruby
# app/jobs/send_welcome_email_job.rb
class SendWelcomeEmailJob < ApplicationJob
  self.enqueue_after_transaction_commit = true

  queue_as :default

  def perform(user_id)
    user = User.find(user_id)
    UserMailer.welcome(user).deliver_now
  end
end

# app/models/user.rb
class User < ApplicationRecord
  after_create do
    SendWelcomeEmailJob.perform_later(id)
    # Taak wordt pas ingepland na commit van de CREATE-transactie
    # Geen risico dat de taak wordt uitgevoerd voordat het gebruikersrecord bestaat
  end
end

Met enqueue_after_transaction_commit ingeschakeld, wordt de taak uitgesteld totdat de omsluitende transactie succesvol is afgerond. Als de transactie wordt teruggedraaid, wordt de taak nooit ingepland. Dit elimineert een hele klasse van race conditions die Redis-gebaseerde wachtrijen teisteren.

Concurrency-besturing en prioriteitswachtrijen

Solid Queue biedt ingebouwde concurrency-controles die Sidekiq alleen aanbiedt in de betaalde Enterprise-versie. De optie concurrency_limit beperkt hoeveel taken van een bepaald type gelijktijdig kunnen worden uitgevoerd.

ruby
# app/jobs/api_sync_job.rb
class ApiSyncJob < ApplicationJob
  limits_concurrency to: 3, key: ->(account_id) { "api_sync_#{account_id}" }

  def perform(account_id)
    account = Account.find(account_id)
    ExternalApi.sync(account)
  end
end

Dit garandeert dat maximaal 3 API-synchronisatietaken gelijktijdig per account worden uitgevoerd, waardoor overtredingen van snelheidslimieten worden voorkomen zonder externe coördinatie. Geblokkeerde taken worden opgeslagen in solid_queue_blocked_executions en automatisch vrijgegeven wanneer een slot beschikbaar komt.

Prioriteit werkt op twee niveaus: numerieke prioriteit per taak (lager nummer = hogere prioriteit) en wachtrijvolgorde in de worker-configuratie. Beide niveaus kunnen worden gecombineerd voor fijnmazige controle over de uitvoeringsvolgorde van taken.

Interview-inzicht

Een veelgestelde vraag in Rails 8-interviews betreft de afwegingen tussen Solid Queue en Sidekiq. Het cruciale verschil: Solid Queue biedt transactionele garanties en ingebouwde concurrency-controles zonder extra kosten. Sidekiq wint op pure doorvoersnelheid voor workloads met hoog volume (10.000+ taken per minuut) doordat Redis in het geheugen werkt. Voor 95% van alle applicaties levert Solid Queue voldoende prestaties. Gedetailleerde benchmarks zijn te vinden in de vergelijking van Rails-achtergrondtaaksystemen.

Job-batches voor gegroepeerde operaties

Solid Queue 1.7.0 introduceerde job-batches, waarmee taken als set kunnen worden gegroepeerd en gevolgd. Deze functionaliteit maakt callbacks mogelijk wanneer alle taken in een batch zijn voltooid, een patroon dat voorheen Sidekiq Pro vereiste.

ruby
# app/jobs/batch_import_job.rb
class BatchImportJob < ApplicationJob
  def perform(file_id)
    file = ImportFile.find(file_id)
    
    SolidQueue::Batch.enqueue(
      on_finish: BatchFinishedJob,
      on_success: NotifyUserJob,
      on_failure: AlertOpsJob
    ) do |batch|
      file.rows.each_slice(100) do |rows|
        ProcessRowsJob.perform_later(rows.map(&:id))
      end
    end
  end
end

De batch volgt alle taken die binnen zijn blok worden ingepland. Wanneer alle taken zijn voltooid, wordt on_finish geactiveerd, ongeacht succes of falen. Als alle taken slagen, wordt on_success geactiveerd. Als een taak faalt, wordt on_failure geactiveerd. Dit maakt workflows mogelijk zoals importverwerking, waar een laatste stap moet wachten tot alle delen zijn voltooid.

Taken die buiten een batch worden aangemaakt maar erbinnen worden ingepland, voegen zich bij die batch. Een batch die eindigt zonder taken wordt onmiddellijk voltooid en activeert direct zijn callbacks.

Fiber-uitvoeringsmodus voor I/O-gebonden workloads

Solid Queue 1.6.0 voegde fiber-gebaseerde worker-uitvoering toe met behulp van de Async gem. Deze modus voert taken uit op fibers in plaats van threads, wat voordelig is voor I/O-gebonden workloads zoals LLM API-aanroepen, waar de meeste tijd wordt besteed aan het wachten op responses.

ruby
# config/solid_queue.yml
production:
  workers:
    - queues: [llm_calls, external_apis]
      fibers: 100
      polling_interval: 0.5

Met 100 fibers kunnen 100 gelijktijdige I/O-gebonden taken in een enkel proces worden uitgevoerd met minimale geheugenoverhead. Dit is gunstiger dan 100 threads, die aanzienlijk meer geheugen zouden verbruiken en contentieproblemen op de GVL (Global VM Lock) zouden ondervinden.

De fiber-modus vereist dat Rails is geconfigureerd voor fiber-isolatie:

ruby
# config/application.rb
config.active_support.isolation_level = :fiber

CPU-gebonden taken moeten threads blijven gebruiken, aangezien fibers geen voordeel bieden wanneer het werk niet yield naar I/O.

Active Job Continuations in Rails 8.1

Rails 8.1 introduceerde Active Job Continuations, waarmee langlopende taken kunnen pauzeren en hervatten vanaf checkpoints. Dit lost het probleem op van taken die opnieuw moeten beginnen bij deploys of container-herstarts.

ruby
# app/jobs/process_import_job.rb
class ProcessImportJob < ApplicationJob
  include ActiveJob::Continuable

  def perform(import_id)
    @import = Import.find(import_id)

    step :validate do
      @import.validate!
    end

    step :process_records do |step|
      @import.records.find_each(start: step.cursor) do |record|
        record.process
        step.advance!(from: record.id)
      end
    end

    step :finalize do
      @import.mark_complete!
    end
  end
end

De step-methode definieert discrete fasen. Als de taak wordt onderbroken, hervat deze vanaf de laatste voltooide stap. Binnen een stap volgt step.cursor de voortgang: step.advance!(from: record.id) slaat de cursorpositie op. Bij hervatting pakt find_each(start: step.cursor) op waar de verwerking was gebleven.

Adapter-vereiste

Continuations vereisen dat de queue-adapter stopping? implementeert. Solid Queue ondersteunt dit sinds v1.2.0. Delayed Job en Resque ondersteunen geen graceful onderbreking zonder extra werk.

De cursor kan elke serialiseerbare waarde zijn. Voor geneste loops wordt een array gebruikt:

ruby
step :process_nested, start: [0, 0] do |step|
  Account.find_each(start: step.cursor[0]) do |account|
    account.records.find_each(start: step.cursor[1]) do |record|
      record.process
      step.set!([account.id, record.id + 1])
    end
    step.set!([account.id + 1, 0])
  end
end

Terugkerende taken zonder Cron

Solid Queue vervangt cron-gebaseerde planning door een ingebouwde scheduler. Terugkerende taken worden gedefinieerd in een YAML-configuratiebestand en beheerd door het scheduler-proces.

ruby
# config/recurring.yml
production:
  cleanup_expired_sessions:
    class: CleanupExpiredSessionsJob
    schedule: every 6 hours
  daily_report:
    class: DailyReportJob
    schedule: every day at 6am
    queue: reports
  weekly_digest:
    class: WeeklyDigestJob
    schedule: every Monday at 9am

Het scheduler-proces leest dit bestand en plant de juiste taken in op de gedefinieerde intervallen. In tegenstelling tot cron draait het binnen dezelfde processupervisor en deelt het dezelfde databaseverbinding. Tijdzone-ondersteuning is toegevoegd in Solid Queue 1.5.0.

Deployment met Puma-integratie

Rails 8 met Kamal biedt zero-configuratie deployment voor Solid Queue. Het instellen van SOLID_QUEUE_IN_PUMA=1 geeft Puma de opdracht om Solid Queue-processen te forken en te superviseren naast de webserver.

ruby
# config/puma.rb (Rails 8 standaard)
plugin :solid_queue if ENV["SOLID_QUEUE_IN_PUMA"]

Dit single-process deployment-model vereenvoudigt containerorkestratie. Eén Docker-image draait zowel de webserver als de taakverwerkers, waardoor de operationele overhead voor kleine tot middelgrote applicaties afneemt.

Klaar om je Ruby on Rails gesprekken te halen?

Oefen met onze interactieve simulatoren, flashcards en technische tests.

Solid Cache: schaalbare database-backed caching

Solid Cache is een database-backed ActiveSupport::Cache::Store die de prestaties van moderne SSD's benut om Redis en Memcached te vervangen als standaard cache-opslag. De premisse: SSD's zijn slechts marginaal langzamer dan RAM voor leesbewerkingen, maar bieden ordes van grootte meer opslagcapaciteit tegen een fractie van de kosten. Solid Cache draait in productie bij Basecamp met 10 TB aan data en 60 dagen retentie, waarbij de P95-rendertijden zijn gehalveerd.

Solid Cache gebruikt een FIFO-verwijderingsstrategie (First In, First Out) in plaats van LRU (Least Recently Used). Hoewel FIFO theoretisch minder efficiënt is, compenseert de veel grotere opslagcapaciteit: items blijven veel langer in de cache, waardoor het totale aantal cache-misses daalt.

ruby
# config/environments/production.rb
config.cache_store = :solid_cache_store

# config/solid_cache.yml
production:
  databases:
    - cache
  store_options:
    max_age: 604800        # 1 week in seconden
    max_size: 256           # Max itemgrootte in KB
    namespace: "app_v1"
    expiry_batch_size: 100  # Items opgeruimd per vervalcyclus

Cache-architectuur en verwijderingsmechanisme

Solid Cache houdt schrijfbewerkingen bij met een interne teller. Wanneer de teller 50% van de geconfigureerde expiry_batch_size bereikt, wordt een achtergrondtaak geactiveerd om verlopen items op te ruimen. Deze geamortiseerde aanpak voorkomt de stop-the-world-pauzes die kunnen optreden bij LRU-verwijdering in geheugenbeperkte Redis-instanties.

De tabel solid_cache_entries slaat alle gecachte gegevens op:

ruby
# db/cache_schema.rb (gegenereerd door installer)
create_table :solid_cache_entries do |t|
  t.binary :key, null: false, limit: 1024
  t.binary :value, null: false, limit: 262144  # 256 KB standaard
  t.datetime :created_at, null: false
  t.index :key, unique: true
  t.index :created_at  # Voor FIFO-verwijdering
end

Lees- en schrijfbewerkingen naar deze tabel gebruiken standaard dezelfde connection pool als de rest van de applicatie. Voor applicaties met veel verkeer voorkomt het configureren van een aparte database voor cachegegevens dat cache-operaties de prestaties van de primaire database beïnvloeden.

Aparte databaseconfiguratie voor cache

Het isoleren van Solid Cache op een dedicated database is eenvoudig en wordt aanbevolen voor productie-workloads die significant cacheverkeer genereren.

yaml
# config/database.yml
production:
  primary:
    <<: *default
    database: myapp_production
  cache:
    <<: *default
    database: myapp_cache_production
    migrations_paths: db/cache_migrate

Deze scheiding garandeert dat miljoenen cache-schrijfbewerkingen niet de WAL (Write-Ahead Log) van de primaire database opblazen of concurreren om connection pool-slots met applicatiequery's.

Productie-overweging

Zonder een aparte database nemen lees- en schrijfbewerkingen van Solid Cache deel aan elke omsluitende ActiveRecord-transactie. Dit betekent dat een langlopende transactie cache-items in een niet-gecommitte status houdt. Configureer voor productieapplicaties altijd een dedicated cache-database.

Sharding en versleuteling

Solid Cache ondersteunt het sharden van gecachte gegevens over meerdere databases om de belasting te verdelen. Het ondersteunt tevens versleutelde attributen, waarbij gecachte gegevens versleuteld blijven in rust, een compliance-vereiste voor applicaties die gevoelige informatie verwerken.

ruby
# config/solid_cache.yml
production:
  databases:
    - cache_shard_1
    - cache_shard_2
    - cache_shard_3
  store_options:
    max_age: 1209600  # 2 weken

Items worden over shards verdeeld met behulp van consistent hashing op de cache-sleutel. Het toevoegen of verwijderen van shards veroorzaakt een tijdelijke toename van cache-misses terwijl items worden herverdeeld, maar er treedt geen gegevensverlies op.

Monitoring met Mission Control Jobs

Mission Control Jobs biedt een webdashboard voor het inspecteren en beheren van Solid Queue-taken. Het toont workers, wachtrijen en taakstatussen (actief, voltooid, geblokkeerd, mislukt) via een gemounte Rails-engine.

ruby
# config/routes.rb
Rails.application.routes.draw do
  mount MissionControl::Jobs::Engine, at: "/jobs"
end

# Gemfile
gem "mission_control-jobs", ">= 1.0.1"

Mission Control biedt ook een console-API voor bulkoperaties op mislukte taken:

ruby
# Rails-console
ActiveJob.jobs.failed.where(job_class: "ApiSyncJob").retry_all
ActiveJob.jobs.failed.where(job_class: "BrokenJob").discard_all

Deze programmatische toegang is essentieel voor het afhandelen van grootschalige taakfouten zonder handmatig door een dashboard te hoeven klikken.

Bronnen

Belangrijke vragen voor technische interviews

Rails 8-interviews richten zich steeds meer op de Solid-stack. Hieronder de meest voorkomende vragen, samen met de verwachte diepgang van het antwoord.

V: Hoe bereikt Solid Queue gelijktijdige taakverwerking zonder Redis? Solid Queue gebruikt FOR UPDATE SKIP LOCKED, een SQL-clausule die meerdere workers in staat stelt dezelfde tabel te bevragen zonder elkaar te blokkeren. Elke worker vergrendelt een batch rijen, verwerkt deze en verwijdert de uitvoeringsrecords. Andere workers slaan reeds vergrendelde rijen over en claimen andere taken.

V: Welk probleem lost transactionele enqueueing op? Het voorkomt dat taken worden uitgevoerd voordat de databasetransactie die ze heeft aangemaakt is gecommit. Zonder deze garantie zou een taak kunnen verwijzen naar een record dat is teruggedraaid, wat resulteert in ActiveRecord::RecordNotFound-fouten.

V: Waarom gebruikt Solid Cache FIFO in plaats van LRU? FIFO is eenvoudiger te implementeren in een database en vermijdt de schrijfversterking van het bijwerken van toegangstijdstempels bij elke leesbewerking. Het nadeel wordt gecompenseerd door de SSD-capaciteit: items blijven langer bewaard, zodat de hitrate hoog blijft ondanks de minder optimale verwijderingsstrategie.

V: Hoe werken job-batches in Solid Queue? Taken die worden ingepland binnen een SolidQueue::Batch.enqueue-blok worden samen gevolgd. De batch activeert on_finish wanneer alle taken zijn voltooid, on_success als alle taken slagen, of on_failure als een taak faalt. Dit maakt workflows mogelijk zoals batch-imports, waar een laatste stap afhankelijk is van de voltooiing van alle delen.

V: Wat zijn Active Job Continuations en wanneer moeten ze worden gebruikt? Continuations stellen langlopende taken in staat hun voortgang op te slaan als checkpoint en na een onderbreking te hervatten. Ze zijn bedoeld voor taken die grote datasets verwerken, zoals imports of batch-updates, waar opnieuw beginnen bij elke deploy aanzienlijke tijd en resources zou verspillen.

V: Wanneer moet een applicatie nog steeds Redis gebruiken in plaats van de Solid-stack? Redis blijft superieur voor applicaties die meer dan 10.000 taken per minuut verwerken, voor workloads die cache-leestijden onder een milliseconde vereisen, of voor applicaties die Redis al voor andere doeleinden gebruiken (Pub/Sub, snelheidsbeperking, sessieopslag). De Solid-stack richt zich op eenvoud, niet op maximale doorvoersnelheid.

Oefen deze en meer vragen op SharpSkills ActiveJob & Achtergrondtaken-module en de Caching-strategieën-module.

Klaar om je Ruby on Rails gesprekken te halen?

Oefen met onze interactieve simulatoren, flashcards en technische tests.

Wat te onthouden over Solid Queue en Solid Cache in Rails 8

  • Solid Queue vervangt Redis-gebaseerde taakwachtrijen door een database-backed oplossing met FOR UPDATE SKIP LOCKED voor gelijktijdige verwerking
  • Transactionele enqueueing elimineert race conditions tussen databaseschrijfbewerkingen en taakuitvoering, een garantie die Redis niet kan bieden
  • Job-batches (v1.7.0) maken gegroepeerde operaties met voltooiings-callbacks mogelijk, voorheen een Sidekiq Pro-functionaliteit
  • De fiber-uitvoeringsmodus (v1.6.0) verbetert de doorvoer voor I/O-gebonden workloads zoals LLM API-aanroepen
  • Active Job Continuations (Rails 8.1) stellen langlopende taken in staat checkpoints op te slaan en na een onderbreking te hervatten
  • Ingebouwde concurrency-controles, terugkerende taken en Puma-integratie worden zonder extra kosten meegeleverd met Solid Queue
  • Solid Cache gebruikt SSD-backed FIFO-caching met optionele sharding en versleuteling, en verwijdert Memcached en Redis uit de infrastructuurstack
  • Een aparte databaseconfiguratie voor Solid Cache voorkomt dat cache-operaties de prestaties van de primaire database beïnvloeden
  • Mission Control Jobs biedt productiemonitoring en bulktaakbeheer via een webdashboard en console-API
  • Voor de meeste Rails 8-applicaties in 2026 is de Solid-stack de aanbevolen standaardkeuze. Redis blijft alleen de voorkeur voor high-throughput edge cases die meer dan 10.000 taken per minuut overschrijden

Begin met oefenen!

Test je kennis met onze gespreksimulatoren en technische tests.

Dagelijkse challenge

Zie jij de bug in Ruby on Rails?

Een echt codefragment, een verborgen bug, één poging per dag. Zonder account uit te proberen.

Anthony Fillion-Maillet

Geschreven door

Anthony Fillion-Maillet

Oprichter van SharpSkill

Al meer dan 10 jaar fullstack-ontwikkelaar. Hij leidt SharpSkill en staat in voor alles wat hier verschijnt.

Bijgewerkt op 10 oktober 2026

Tags

#ruby-on-rails
#solid-queue
#solid-cache
#rails-8
#background-jobs
#caching
#interview

Delen

Gerelateerde artikelen