Solid Queue et Solid Cache dans Rails 8 : Guide complet pour les entretiens techniques 2026

Analyse approfondie de Solid Queue et Solid Cache, les solutions par défaut basées sur la base de données dans Rails 8. Architecture, configuration, contrôle de concurrence et connaissances clés pour les entretiens techniques en 2026.

Architecture Solid Queue et Solid Cache dans Rails 8 avec traitement de jobs et cache adossés à la base de données

Solid Queue et Solid Cache marquent le tournant infrastructurel le plus important de l'histoire de Rails. Ces deux composants sont désormais les choix par défaut dans Rails 8, remplaçant Redis pour les tâches en arrière-plan et la mise en cache par des alternatives adossées à la base de données, éliminant ainsi une couche entière de complexité opérationnelle.

Le triptyque Solid

Rails 8 adopte par défaut trois composants adossés à la base de données : Solid Queue (tâches en arrière-plan), Solid Cache (cache) et Solid Cable (WebSockets). Ensemble, ils suppriment la dépendance à Redis pour la majorité des applications Rails. Ce sujet revient fréquemment dans les entretiens techniques Rails 8.

Comment Solid Queue remplace les backends de jobs basés sur Redis

Solid Queue est un backend Active Job adossé à la base de données qui stocke les jobs directement dans PostgreSQL, MySQL ou SQLite. Le mécanisme central repose sur FOR UPDATE SKIP LOCKED — une fonctionnalité SQL disponible dans PostgreSQL 9.5+ et MySQL 8+ qui transforme une simple table relationnelle en file d'attente concurrente sans verrouillage bloquant.

L'architecture repose sur trois composants :

  • Workers : interrogent la table solid_queue_ready_executions et réservent les jobs via SKIP LOCKED
  • Dispatchers : déplacent les jobs planifiés depuis solid_queue_scheduled_executions vers la table des jobs prêts lorsque leur heure d'exécution arrive
  • Schedulers : gèrent les tâches récurrentes définies dans la configuration
ruby
# config/solid_queue.yml
production:
  dispatchers:
    - polling_interval: 1
      batch_size: 500
  workers:
    - queues: "*"
      threads: 5
      polling_interval: 0.1
      processes: 2

Cette configuration lance deux processus worker avec 5 threads chacun, interrogeant la base toutes les 100 ms. Le dispatcher vérifie les jobs planifiés toutes les secondes par lots de 500.

L'enqueuing transactionnel dans Rails 8

L'un des arguments les plus solides en faveur de Solid Queue par rapport aux backends Redis est l'enqueuing transactionnel. Lorsqu'un job est mis en file d'attente au sein d'une transaction de base de données, il ne devient visible qu'après le commit de la transaction. Les backends basés sur Redis ne peuvent pas offrir cette garantie — un job pourrait s'exécuter avant la fin de la transaction qui l'a créé, référençant des enregistrements qui n'existent pas encore.

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)
    # Job only enqueued after the CREATE transaction commits
    # No risk of the job running before the user record exists
  end
end

Avec enqueue_after_transaction_commit activé, le job est différé jusqu'à ce que la transaction englobante réussisse. Si la transaction est annulée (rollback), le job n'est jamais mis en file d'attente. Cela élimine toute une catégorie de conditions de concurrence qui affectent les files d'attente Redis.

Contrôles de concurrence et files prioritaires

Solid Queue intègre des contrôles de concurrence natifs que Sidekiq ne propose que dans sa version Enterprise payante. L'option concurrency_limit restreint le nombre de jobs d'un type donné pouvant s'exécuter simultanément.

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

Cette configuration garantit qu'au maximum 3 jobs de synchronisation API s'exécutent simultanément par compte, empêchant les violations de limites de taux sans coordination externe. Les jobs bloqués sont stockés dans solid_queue_blocked_executions et automatiquement libérés lorsqu'un créneau se libère.

La priorité fonctionne à deux niveaux : priorité numérique par job (un nombre plus petit = priorité plus élevée) et ordre des files dans la configuration du worker. Les deux peuvent être combinés pour un contrôle granulaire de l'ordre d'exécution.

Point clé en entretien

Une question fréquente en entretien Rails 8 porte sur les compromis entre Solid Queue et Sidekiq. Le facteur déterminant : Solid Queue offre des garanties transactionnelles et des contrôles de concurrence intégrés sans coût supplémentaire. Sidekiq l'emporte en débit brut pour les charges de travail à haut volume (10 000+ jobs/minute) grâce au stockage en mémoire de Redis. Pour 95 % des applications, Solid Queue offre des performances suffisantes.

Jobs récurrents sans cron

Solid Queue remplace la planification basée sur cron par un scheduler intégré. Les tâches récurrentes sont définies dans un fichier de configuration YAML et gérées par le processus scheduler.

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

Le processus scheduler lit ce fichier et met en file d'attente les jobs appropriés aux intervalles définis. Contrairement à cron, il s'exécute au sein du même superviseur de processus et partage la même connexion à la base de données.

Déploiement avec intégration Puma

Rails 8 avec Kamal offre un déploiement sans configuration pour Solid Queue. Le paramètre SOLID_QUEUE_IN_PUMA=1 indique à Puma de forker et superviser les processus Solid Queue aux côtés du serveur web.

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

Ce modèle de déploiement mono-processus simplifie l'orchestration des conteneurs. Une seule image Docker fait tourner à la fois le serveur web et les processeurs de jobs, réduisant la charge opérationnelle pour les applications de petite et moyenne taille.

Prêt à réussir tes entretiens Ruby on Rails ?

Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.

Solid Cache : le cache adossé à la base de données qui passe à l'échelle

Solid Cache est un ActiveSupport::Cache::Store adossé à la base de données qui tire parti des performances des SSD modernes pour remplacer Redis et Memcached comme cache par défaut. Le postulat : les SSD ne sont que marginalement plus lents que la RAM pour les opérations de lecture, mais offrent des capacités de stockage considérablement supérieures à un coût bien moindre.

Solid Cache utilise une stratégie d'expiration FIFO (First In, First Out) plutôt que LRU (Least Recently Used). Bien que le FIFO soit théoriquement moins efficace, la capacité de stockage bien supérieure compense : les entrées restent en cache beaucoup plus longtemps, réduisant le nombre de cache misses au global.

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 seconds
    max_size: 256           # Max entry size in KB
    namespace: "app_v1"
    expiry_batch_size: 100  # Entries cleaned per expiry cycle

Architecture du cache et mécanisme d'expiration

Solid Cache suit les écritures à l'aide d'un compteur interne. Lorsque ce compteur atteint 50 % de la taille configurée expiry_batch_size, une tâche de nettoyage en arrière-plan se déclenche pour supprimer les entrées expirées. Cette approche amortie évite les pauses de type stop-the-world qui peuvent survenir lors de l'éviction LRU dans des instances Redis contraintes en mémoire.

La table solid_cache_entries stocke toutes les données mises en cache :

ruby
# db/cache_schema.rb (generated by installer)
create_table :solid_cache_entries do |t|
  t.binary :key, null: false, limit: 1024
  t.binary :value, null: false, limit: 262144  # 256 KB default
  t.datetime :created_at, null: false
  t.index :key, unique: true
  t.index :created_at  # For FIFO expiry
end

La lecture et l'écriture dans cette table utilisent par défaut le même pool de connexions que le reste de l'application. Pour les applications à fort trafic, configurer une base de données dédiée au cache empêche les opérations de cache d'impacter les performances de la base principale.

Configuration d'une base de données dédiée au cache

Isoler Solid Cache sur une base de données dédiée est simple et recommandé pour les environnements de production générant un trafic de cache significatif.

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

Cette séparation garantit que des millions d'opérations d'écriture de cache ne gonflent pas le WAL (Write-Ahead Log) de la base primaire ni ne monopolisent les créneaux du pool de connexions pour les requêtes applicatives.

Considération production

Sans base de données séparée, les lectures et écritures de Solid Cache participent à toute transaction ActiveRecord englobante. Cela signifie qu'une transaction longue maintient les entrées de cache dans un état non commité. Il est impératif de configurer une base de données de cache dédiée pour les applications en production.

Sharding et chiffrement

Solid Cache supporte le sharding des données en cache sur plusieurs bases de données pour répartir la charge. Il prend également en charge les attributs chiffrés — les données en cache restent chiffrées au repos, une exigence de conformité pour les applications traitant des informations sensibles.

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

Les entrées sont distribuées entre les shards via un hachage cohérent sur la clé de cache. L'ajout ou la suppression de shards provoque une augmentation temporaire des cache misses pendant la redistribution, mais aucune perte de données ne survient.

Monitoring avec Mission Control Jobs

Mission Control Jobs fournit un tableau de bord web pour inspecter et gérer les jobs Solid Queue. Il affiche les workers, les files et les états des jobs (en cours, terminés, bloqués, échoués) via un engine Rails monté.

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 expose également une API console pour les opérations en masse sur les jobs échoués :

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

Cet accès programmatique est essentiel pour gérer les échecs de jobs à grande échelle sans avoir à cliquer manuellement dans un tableau de bord.

Questions techniques clés pour les entretiens

Les entretiens Rails 8 se concentrent de plus en plus sur le stack Solid. Voici les questions qui reviennent le plus souvent, avec le niveau de détail attendu dans les réponses.

Q : Comment Solid Queue parvient-il à traiter les jobs de manière concurrente sans Redis ? Solid Queue utilise FOR UPDATE SKIP LOCKED, une clause SQL qui permet à plusieurs workers d'interroger la même table sans se bloquer mutuellement. Chaque worker verrouille un lot de lignes, les traite, puis supprime les enregistrements d'exécution. Les autres workers ignorent les lignes déjà verrouillées et réservent d'autres jobs.

Q : Quel problème l'enqueuing transactionnel résout-il ? Il empêche les jobs de s'exécuter avant que la transaction de base de données qui les a déclenchés ne soit commitée. Sans cela, un job pourrait référencer un enregistrement annulé par un rollback, provoquant des erreurs ActiveRecord::RecordNotFound.

Q : Pourquoi Solid Cache utilise-t-il FIFO plutôt que LRU ? Le FIFO est plus simple à implémenter en base de données et évite l'amplification d'écriture liée à la mise à jour des horodatages d'accès à chaque lecture. Ce compromis est compensé par la capacité SSD — les entrées vivent plus longtemps, le taux de succès du cache reste élevé malgré une stratégie d'éviction moins optimale.

Q : Dans quels cas une application devrait-elle encore utiliser Redis plutôt que le stack Solid ? Redis reste supérieur pour les applications traitant plus de 10 000 jobs par minute, les charges nécessitant des lectures cache en dessous de la milliseconde, ou les applications utilisant déjà Redis pour d'autres fonctions (Pub/Sub, rate limiting, stockage de sessions). Le stack Solid vise la simplicité, pas le débit maximal.

Ces questions et bien d'autres peuvent être pratiquées sur les modules ActiveJob & Background Jobs et Stratégies de cache de SharpSkill.

Prêt à réussir tes entretiens Ruby on Rails ?

Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.

Conclusion

  • Solid Queue remplace les files de jobs Redis par une solution adossée à la base de données utilisant FOR UPDATE SKIP LOCKED pour le traitement concurrent
  • L'enqueuing transactionnel élimine les conditions de concurrence entre les écritures en base et l'exécution des jobs — une garantie que Redis ne peut pas offrir
  • Les contrôles de concurrence intégrés, les jobs récurrents et l'intégration Puma sont inclus dans Solid Queue sans coût supplémentaire
  • Solid Cache utilise un cache FIFO adossé aux SSD avec sharding et chiffrement optionnels, supprimant Memcached et Redis de la pile infrastructure
  • La configuration d'une base de données séparée pour Solid Cache empêche les opérations de cache d'impacter les performances de la base primaire
  • Mission Control Jobs fournit un monitoring en production et une gestion en masse des jobs via un tableau de bord web et une API console
  • Pour la majorité des applications Rails 8 en 2026, le stack Solid est le choix par défaut recommandé — Redis reste pertinent uniquement pour les cas de haute charge dépassant 10 000 jobs par minute

Passe à la pratique !

Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.

Tags

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

Partager

Articles similaires