activerecord

Deterministic Sorting with Secondary Key

If you sort by a non-unique column (score, created_at), pagination can “skip” or “duplicate” records. Always add a secondary unique key like id for deterministic ordering.

Use `touch_all` for Efficient “Bump Updated At”

When you need to invalidate caches by changing timestamps, use touch_all to avoid per-record callbacks. It’s fast, explicit, and doesn’t run unintended side effects.

Safe Pagination with Keyset (No OFFSET)

OFFSET gets slower as tables grow and becomes inconsistent under writes. Keyset pagination is stable and fast: paginate by (created_at, id) cursor. This is a common “senior Rails” upgrade for activity feeds.

Avoid Memory Blowups: find_each + select Columns

Backfills often fail because we accidentally load full records and associations. Use select to fetch only needed columns and find_each to keep memory flat. This is basic, but it’s where outages come from.

Prevent Long Transactions with after_save_commit for Heavy Work

Heavy work inside a transaction increases lock time and deadlock risk. Use after_save_commit to schedule slow tasks (thumb generation, external sync) once the write is durable.

Safer Deletion with dependent: :restrict_with_error

Sometimes cascading deletes are the wrong UX and the wrong ops story. Restrict deletion when children exist and provide a user-facing error. This prevents data loss accidents.

Counter Cache Repair Job (Consistency Tooling)

Counter caches drift (deleted records, backfills, manual SQL). A repair job that recomputes counts safely is invaluable. It’s the kind of operational code you’re glad you wrote the first time a dashboard is wrong.

Read Replica Routing for GET-Heavy Endpoints

For apps with replicas, route read-only code paths to reading role and enforce prevent_writes. This is a strong reliability move: accidental writes on replicas become exceptions instead of silent data loss.

Keep DB Connections Healthy in Long Jobs

Long-running jobs can hit stale connections. Wrap work in with_connection and consider verify! before heavy DB usage. This reduces “PG::ConnectionBad” noise during long maintenance tasks.

Transactionally Create Parent + Children with accepts_nested_attributes_for

Nested writes should be transactional: either everything is created or nothing is. Rails does this well when you keep validations coherent and avoid side effects in callbacks.

Targeted Query Caching for Expensive Endpoints

I’ve had endpoints where the same lookups get repeated across helpers and partials, and I didn’t want to pay for query caching on every request. In Scoped query cache, I wrap only the expensive report build in ActiveRecord::Base.cache, so the cache li

ActiveRecord::Relation as a Boundary (No Arrays)

Return relations from query objects, not arrays. It keeps composition possible (additional filters, pagination, eager loading) and avoids loading huge result sets accidentally.