Skip to main content

ActiveRecord where vs find_by — Which to Use When

where returns a relation, find_by returns one record or nil. Here's when each is correct, what breaks if you pick wrong, and Rails 7/8 production patterns.

A
Raza Hussain
· 3 min read · 13
ActiveRecord where vs find_by — Which to Use When

Most Rails developers use where and find_by interchangeably early on. That works until it doesn’t.

The Core Difference

find_by executes immediately and returns one record (or nil):

User.find_by(email: "raza@example.com")
# SELECT * FROM users WHERE email = 'raza@example.com' LIMIT 1
# => #<User ...> or nil

where returns an ActiveRecord::Relation — it doesn’t hit the database until you call something that forces execution:

User.where(email: "raza@example.com")
# => ActiveRecord::Relation  (not executed yet)

User.where(email: "raza@example.com").first
# SELECT * FROM users WHERE email = 'raza@example.com' LIMIT 1

When find_by Is the Right Call

Use find_by when:

  • You expect zero or one record
  • You want nil back if nothing matches (not an exception)
  • You are done chaining after this call
account = Account.find_by(subdomain: params[:subdomain])
return render :not_found unless account

find_by(id: x) is safer than find(x) — returns nil instead of raising ActiveRecord::RecordNotFound. Use find only when absence is a bug.

When where Is the Right Call

Use where when:

  • You expect multiple records
  • You need to chain more conditions, scopes, or ordering
  • You are building a query progressively
User.where(role: "admin").where("created_at > ?", 1.week.ago).order(:name)

where composes cleanly with scopes:

User.active.where(plan: "pro").limit(20)

find_by cannot chain. The moment you need another condition or ordering, use where.

The Trap: find_by with Multiple Conditions

User.find_by(role: "admin", active: true)
# Returns ONE admin user — whichever the DB returns first

If you meant all admin users, this silently gives you one. Use where.

What About find?

find raises ActiveRecord::RecordNotFound if the record is missing:

User.find(params[:id])
# Raises if not found — Rails handles the 404 for you

Use find in controller show actions. Use find_by when you will handle nil yourself.

Performance

No difference in the query itself. Both generate the same SQL for single-record lookups. find_by adds LIMIT 1 automatically.

Quick Reference

Method Returns Raises if missing Chainable
find single record yes no
find_by single record or nil no no
where Relation no yes

The Rule

  • One record, done: find_by
  • One record, absence is a bug: find
  • Multiple records or chaining: where

Check every find_by in your codebase where you immediately call .first or .last on the result. That is where(…).first and should be written explicitly. Learn more about rails in our guide: Does ActiveRecord find_by Return nil? (Guide 2026).

Was this article helpful?

Your feedback helps us improve our content

Be the first to vote!

How We Verify Conversions

Every conversion shown on this site follows a strict verification process to ensure correctness:

  • Compare results on same dataset — We run both SQL and ActiveRecord against identical test data and verify results match
  • Check generated SQL with to_sql — We inspect the actual SQL Rails generates to catch semantic differences (INNER vs LEFT JOIN, WHERE vs ON, etc.)
  • Add regression tests for tricky cases — Edge cases like NOT EXISTS, anti-joins, and predicate placement are tested with multiple scenarios
  • Tested on Rails 8.1.1 — All conversions verified on current Rails version to ensure compatibility

Last updated: October 03, 2026

Try These Queries in Our Converter

See the SQL examples from this article converted to ActiveRecord—and compare the SQL Rails actually generates.

13

Leave a Response

Responses (0)

No responses yet

Be the first to share your thoughts

R

Raza Hussain

Full-stack developer specializing in Ruby on Rails, React, and modern JavaScript. 15+ years upgrading and maintaining production Rails apps. Led Rails 4/5 → 7 upgrades with 40% performance gains, migrated apps from Heroku to Render cutting costs by 35%, and built systems for StatusGator, CryptoZombies, and others. Available for Rails upgrades, performance work, and cloud migrations.

💼 15 years experience 📝 50 posts