.claude/skills/performance-optimization/SKILL.md
Identifies and fixes Rails performance issues including N+1 queries, slow queries, and memory problems. Use when optimizing queries, fixing N+1 issues, improving response times, or when user mentions performance, slow, optimization, or Bullet gem. WHEN NOT: Caching-specific patterns (use caching-strategies), adding new features, or general code quality improvements unrelated to speed.
npx skillsauth add ThibautBaissac/rails_ai_agents performance-optimizationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Performance optimization focuses on:
# Gemfile
group :development, :test do
gem 'bullet' # N+1 detection
gem 'rack-mini-profiler' # Request profiling
gem 'memory_profiler' # Memory analysis
end
N+1 queries occur when code loads a collection then makes a separate query for each associated record. The Bullet gem detects these automatically. Fix them with eager loading via includes, preload, or eager_load.
| Method | Use When |
|--------|----------|
| includes | Most cases (Rails chooses best strategy) |
| preload | Forcing separate queries, large datasets |
| eager_load | Filtering on association, need single query |
| joins | Only need to filter, don't need association data |
Key patterns: Bullet configuration, eager loading methods, scoped eager loading, counter caches, N+1 specs with query count assertions.
See references/n-plus-one.md for all code examples and patterns.
Optimize queries by selecting only needed columns, using batch processing for large datasets, and choosing efficient existence checks.
| Pattern | Bad | Good |
|---------|-----|------|
| Column selection | User.all.map(&:name) | User.pluck(:name) |
| Large iterations | Event.all.each { ... } | Event.find_each { ... } |
| Existence checks | .any? / .present? | .exists? |
| Collection size | .length (loads all) | .size (smart) |
Add indexes for: foreign keys, columns in WHERE/ORDER BY/JOIN clauses, and unique constraints. Use composite indexes for multi-column queries. Use partial indexes for filtered subsets.
Use Event.where(...).explain(:analyze) to inspect query plans. Set up slow query logging via ActiveSupport::Notifications to catch queries over a threshold.
See references/query-optimization.md for all code examples and patterns.
Use memory_profiler to detect memory issues. Prefer pluck over loading full AR objects, use find_each for streaming, and use update_all / in_batches for bulk operations.
Provides per-request profiling in development. Shows query count, timing, and flamegraphs (with stackprof gem). Access via the profiler badge or ?pp=flamegraph.
See references/memory-and-profiling.md for all code examples and patterns.
| Problem | Solution |
|---------|----------|
| N+1 on belongs_to | includes(:association) |
| N+1 on has_many | includes(:association) |
| Slow COUNT | Add counter_cache |
| Loading all columns | Use select or pluck |
| Large dataset iteration | Use find_each |
| Missing index on FK | Add index on *_id columns |
| Slow WHERE clause | Add index on filtered column |
| Loading unused associations | Remove from includes |
explain(:analyze), check slow query logs, profile memorydevelopment
Creates Turbo Streams, Turbo Frames, and morphing patterns for real-time UI updates. Use when adding real-time updates, partial page rendering, form submissions, or broadcasting. WHEN NOT: For Stimulus JavaScript controllers (see stimulus-patterns skill). For general view conventions (see rules/views.md).
testing
Writes Minitest tests with fixtures following 37signals conventions. Uses Minitest (not RSpec) and fixtures (not factories). Use when writing tests, adding test coverage, or creating fixtures. WHEN NOT: For RSpec or FactoryBot patterns (this project uses Minitest + fixtures exclusively). For test configuration/CI setup (see project docs).
tools
Builds focused, single-purpose Stimulus controllers for progressive enhancement. Use when adding JavaScript behavior, UI interactions, form enhancements, or building reusable client-side components. WHEN NOT: For Turbo Stream/Frame patterns (see turbo-patterns skill). For server-side view logic (see rules/views.md).
testing
Implements the state-as-records-not-booleans pattern for rich state tracking. Use when modeling state changes, replacing boolean flags with record-based state, or when user mentions state records, closures, publications, or toggling state. WHEN NOT: Technical flags like cached/processed (use booleans), concern extraction (use concern-patterns), general model work (use model-patterns).