ruby 96 lines · 4 tabs

Transactional Email “Send Once” with Delivered Marker

Shared by codesnips Jan 2026
4 tabs
class CreateEmailDeliveries < ActiveRecord::Migration[7.1]
  def change
    create_table :email_deliveries do |t|
      t.string :dedupe_key, null: false
      t.string :mailer, null: false
      t.string :action, null: false
      t.string :status, null: false, default: "pending"
      t.string :provider_message_id
      t.datetime :sent_at
      t.text :last_error
      t.timestamps
    end

    add_index :email_deliveries, :dedupe_key, unique: true
    add_index :email_deliveries, :status
  end
end
4 files · ruby Explain with highlit

Transactional emails such as receipts, password resets, and order confirmations must reach a user exactly once even though the systems that trigger them are unreliable. Job queues retry on failure, deploys interrupt in-flight work, and a single user action can be processed twice. Sending "at least once" is easy; sending "exactly once" requires a durable marker that records whether a specific email has already gone out. This snippet builds that marker with a dedicated email_deliveries table plus a job that claims a delivery before handing off to the mail provider.

The email_deliveries migration defines the storage. Each intended email is one row keyed by a dedupe_key with a unique index, which is the real enforcement mechanism: even under a race the database rejects a second insert. A status column tracks the lifecycle (pending, sent, failed), and sent_at plus provider_message_id capture proof of delivery for auditing and support tickets.

In EmailDelivery model, claim! is the heart of the pattern. It uses find_or_create_by! on the dedupe_key, so a duplicate trigger returns the existing row rather than creating a new one. The rescue ActiveRecord::RecordNotUnique handles the narrow window where two threads insert simultaneously — one wins, the loser retries the lookup. deliverable? then reports whether the row is still pending, letting callers skip anything already sent.

The SendTransactionalEmailJob ties it together. It calls claim! to obtain the row, and returns early if deliverable? is false, which makes the job safe to run any number of times. Actual sending happens inside a guarded block: on success it records provider_message_id and flips status to sent; on error it marks failed and re-raises so the queue's retry machinery can run again against the same durable row.

The key trade-off is that the marker is committed separately from the send, so a crash between "claimed" and "sent" leaves a pending row that a retry will pick up — favoring an occasional double-send over silent loss only if the provider itself lacks idempotency. Pairing the dedupe_key with a provider-side idempotency key closes that final gap. This approach fits any workflow where re-triggering is expected and duplicate emails are unacceptable.


Related snips

Share this code

Here's the card — post it anywhere.

Transactional Email “Send Once” with Delivered Marker — share card
Link copied