Khác biệt nằm ở quan hệ với transaction của database:
after_save: chạy bên trong transaction, ngay sau khiINSERT/UPDATEđược gửi nhưng trước khiCOMMIT. Nếu về sau transaction rollback, mọi thứafter_savelàm cũng bị hủy theo nếu nằm trong DB — nhưng side-effect ngoài DB (gửi mail, enqueue job) thì không rollback được.after_commit: chỉ chạy sau khiCOMMITthành công, tức dữ liệu đã bền vững. Không chạy nếu transaction rollback.
ruby
class Order < ApplicationRecord
after_save { Rails.logger.info "trong transaction" }
after_commit { PaymentMailer.receipt(self).deliver_later }
endVì sao quan trọng: enqueue background job trong after_save dễ gây race — worker có thể chạy và query record trước khi transaction commit, thấy dữ liệu chưa tồn tại.
Mọi side-effect ra thế giới bên ngoài (mail, job, webhook) nên đặt ở after_commit.