#create_or_find_by is a great addition! We’ve previously used an advisory lock as one of the checks to prevent duplicate records for highly concurrent / write heavy workloads:
existing_record = Record.find_by(
indexed_col_one: val_one,
indexed_col_two: val_two
)
return existing_record if existing_record.present?
Record.with_advisory_lock(name: "create-record-#{val_one}-#{val_two}") do
Record.find_or_create_by!(
indexed_col_one: val_one,
indexed_col_two: val_two
)
end
For the most part this works. With added volume, the locked time incrementally adds up and can be detrimental to performance. So we switched over to using #create_or_find_by and dropped the lock all together.
Record.create_or_find_by!(
indexed_col_one: val_one,
indexed_col_two: val_two
)
In our use case, the record is usually created once and any subsequent call goes though the create/rescue loop leading to a small hit in performance (but overall better than the first example).
So we further optimized these calls by running an initial #find_by to avoid the create/rescue loop for the majority of these calls. In the cases where the record doesn’t exist and was missed in the initial fetch, it runs the risk of 3 total DB operations (SELECT → INSERT → SELECT). We found this specific scenario occurring very infrequently. I’d almost wager than most applications will use the fallback more than have net new inserts when using #create_or_find_by.
existing_record = Record.find_by(
indexed_col_one: val_one,
indexed_col_two: val_two
)
return existing_record if existing_record.present?
Record.create_or_find_by!(
indexed_col_one: val_one,
indexed_col_two: val_two
)
For this reason, I want to introduce an optional find_first flag in #create_or_find_by to standardize this pattern: https://github.com/rails/rails/pull/44885
I’d also love to hear about your experience with #create_or_find_by and about any patterns your team has used with this method. ![]()