This year I will be participating in the 2025 AIDS Lifecycle 🎉
Please consider donating on my rider page 🚲

Threads inside transaction blocks

May 13, 2025 #rails #databases

Beware of using threads that execute database queries inside active record transaction blocks. And yes this includes using gems like parallel with threads too! Modifying the same record in a transaction and within a thread within that transaction can cause deadlocks 🔒This is because the inner thread checks out a different database connection from the pool, which isn't aware of the outer transaction's context as it hasn't been committed yet. This can easily be simulated by running the code below in a Rails console. The 2nd operation times out because it's started from a different DB connection in a new thread, and that 2nd DB connection is waiting for the outer transaction to commit. But the outer transaction never commits because it's waiting on the code within the thread to complete.

ActiveRecord::Base.transaction do
  user = User.find_by(email: 'test@example.com').update!(name: 'Jon')

  Thread.new do
    ActiveRecord::Base.connection_pool.with_connection do
      User.find_by(email: 'test@example.com').update!(name: 'Kevin')
    end
  end.join
end