---
name: rails-postgres-redis
description: "Use when building, refactoring, or reviewing a Ruby on Rails + PostgreSQL + Redis + Sidekiq project (Rails, Ruby, PostgreSQL, Redis, Sidekiq). Production guidelines for Ruby on Rails monoliths, ActiveRecord pool tuning, Redis Sidekiq background jobs, and modern Hotwire or React UI architecture."
license: MIT
metadata:
  source: https://stackitfast.com/rules/rails-postgres-redis
  version: "2026-10-04"
---

# Ruby on Rails + PostgreSQL + Redis + Sidekiq — Agent Skill

## When to use this skill
- Any task that scaffolds, modifies, refactors, or reviews code in a Ruby on Rails + PostgreSQL + Redis + Sidekiq codebase.
- Whenever the project depends on Rails, Ruby, PostgreSQL, Redis, Sidekiq.
- Apply these guidelines before proposing architecture, database, or deployment changes.

## Guidelines
# Project Architecture & Guidelines (Ruby on Rails + PostgreSQL + Redis + Sidekiq)

## 1. System Architecture
- **Framework**: Ruby on Rails 8.1+ (Puma web server). Rails 8 ships Solid Queue and Solid Cache on the database by default; this rule keeps Redis and Sidekiq on purpose, for teams that need Sidekiq's throughput and tooling at scale.
- **Database**: PostgreSQL with ActiveRecord ORM.
- **Caching & Job Store**: Redis for Rails cache store and Sidekiq background job broker.
- **Background Worker**: Sidekiq for asynchronous job processing.

## 2. Database Connection Pool Sizing (ActiveRecord & Puma)
- Ensure database connection pool in `config/database.yml` matches Puma thread count and Sidekiq concurrency:
  ```yaml
  default: &default
    adapter: postgresql
    encoding: unicode
    pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
    timeout: 5000
  ```
- When configuring Sidekiq workers, ensure the process pool size is at least equal to the Sidekiq concurrency setting (`concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY") { 10 } %>`).

## 3. Redis & Sidekiq Configuration
- Initialize Sidekiq in `config/initializers/sidekiq.rb` with dedicated connection pools:
  ```ruby
  Sidekiq.configure_server do |config|
    config.redis = { url: ENV.fetch("REDIS_URL", "redis://localhost:6379/1"), size: ENV.fetch("SIDEKIQ_CONCURRENCY", 10).to_i + 5 }
  end

  Sidekiq.configure_client do |config|
    config.redis = { url: ENV.fetch("REDIS_URL", "redis://localhost:6379/1"), size: ENV.fetch("RAILS_MAX_THREADS", 5).to_i }
  end
  ```

## 4. Safe Database Migrations (Zero-Downtime)
- Use the `strong_migrations` gem to prevent dangerous DDL locks in production.
- Adding Columns with Defaults: In PostgreSQL 11+, `add_column` with default values is instant and safe.
- Creating Indexes: Always use `algorithm: :concurrently` and `disable_ddl_transaction!` when adding indexes to live tables.

## 5. Common Pitfalls to Avoid
- ❌ Passing ActiveRecord Objects to Sidekiq: Pass only record IDs (`user_id`), never entire serialized objects.
- ❌ N+1 Queries: Use `includes(:relation)` or `strict_loading` in ActiveRecord queries.
- ❌ Redis Memory Leaks: Use separate Redis database numbers (`db/0` for cache, `db/1` for Sidekiq) to prevent cache evictions from clearing job queues.

## 6. Testing Conventions
- Use RSpec with `factory_bot` for model/request specs; avoid Rails fixtures, which rot as schemas evolve.
- Test Sidekiq jobs with `sidekiq/testing` in fake mode by default; use `Sidekiq::Testing.inline!` only for explicit integration specs that need real execution.
- Use `strict_loading` in test environments to fail fast on N+1 queries instead of catching them in production APM.
- Run request specs (not just model specs) for every controller action — RSpec model coverage alone misses routing and serialization bugs.

## 7. Git Workflow & PR Conventions
- Conventional Commits (`feat:`, `fix:`, `refactor:`) scoped to the Rails resource, e.g. `fix(invoices): correct Sidekiq retry backoff for failed charges`.
- Migrations ship in the same PR as the model change; run through `strong_migrations` locally before pushing.
- Require `bundle exec rspec` and `bin/rails db:migrate:status` clean before merge.
- Squash-merge; concurrent-index migrations get their own PR, never bundled with unrelated schema changes.

## Source
Maintained at https://stackitfast.com/rules/rails-postgres-redis — also available as AGENTS.md, CLAUDE.md, and Cursor .mdc.