Option 1: Use update_counters

Rails provides a built-in method:
Foobar.increment_counter(:foo_count, foobar.id)
This translates into a SQL query like:
UPDATE foobars SET foo_count = foo_count + 1 WHERE id = X
Because this happens directly in the database in one atomic operation, it’s thread-safe and web-instance-safe.

Option 2: Raw SQL

If you prefer, or need something custom:
Foobar.where(id: foobar.id).update_all("foo_count = foo_count + 1")

Option 3: Database Locking (Pessimistic Lock)

If you absolutely need to perform other operations with the updated object:

Foobar.transaction do
  foobar = Foobar.lock(true).find(foobar.id)
  foobar.foo_count += 1
  foobar.save!
end

This uses a SELECT … FOR UPDATE query, locking the row until the transaction completes. But be cautious: this can reduce performance under high concurrency.

Option 4: PostgreSQL Triggers (Database-level)

Move the increment logic into the database using a trigger:

CREATE FUNCTION increment_foo_count()
RETURNS TRIGGER AS $$
BEGIN
  UPDATE foobars SET foo_count = foo_count + 1 WHERE id = NEW.foobar_id;
  RETURN NEW;
END;

CREATE TRIGGER trigger_increment_foo_count
AFTER INSERT ON foo_count_events
FOR EACH ROW
EXECUTE FUNCTION increment_foo_count();

Then in Rails, you insert a row into foo_count_events, and the database handles the rest.

Need Help With Ruby On Rails Development?

Work with our skilled Ruby on Rails developers to accelerate your project and boost its performance.

Hire Ruby on Rails Developer

Support On Demand!

Related Q&A