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
class EmailDelivery < ApplicationRecord
STATUSES = %w[pending sent failed].freeze
validates :dedupe_key, :mailer, :action, presence: true
validates :status, inclusion: { in: STATUSES }
def self.claim!(dedupe_key:, mailer:, action:)
find_or_create_by!(dedupe_key: dedupe_key) do |delivery|
delivery.mailer = mailer
delivery.action = action
end
rescue ActiveRecord::RecordNotUnique
find_by!(dedupe_key: dedupe_key)
end
def deliverable?
status == "pending"
end
def mark_sent!(provider_message_id)
update!(
status: "sent",
provider_message_id: provider_message_id,
sent_at: Time.current,
last_error: nil
)
end
def mark_failed!(error)
update!(status: "failed", last_error: error.message.truncate(1000))
end
end
class SendTransactionalEmailJob
include Sidekiq::Job
sidekiq_options queue: :mailers, retry: 5
def perform(mailer_name, action, dedupe_key, record_gid)
delivery = EmailDelivery.claim!(
dedupe_key: dedupe_key,
mailer: mailer_name,
action: action
)
return unless delivery.deliverable?
record = GlobalID::Locator.locate(record_gid)
mail = mailer_name.constantize.public_send(action, record)
begin
response = mail.deliver_now
delivery.mark_sent!(extract_message_id(response, mail))
rescue StandardError => e
delivery.mark_failed!(e)
raise
end
end
private
def extract_message_id(response, mail)
response.respond_to?(:message_id) ? response.message_id : mail.message_id
end
end
class OrdersController < ApplicationController
def confirm
@order = Order.find(params[:id])
@order.confirm!
SendTransactionalEmailJob.perform_async(
"OrderMailer",
"confirmation",
"order-confirmation-#{@order.id}",
@order.to_global_id.to_s
)
redirect_to order_path(@order), notice: "Order confirmed."
end
end
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
class CommentsController < ApplicationController
before_action :set_post
def create
@comment = @post.comments.build(comment_params)
System test: asserting Turbo Stream responses
class Post < ApplicationRecord
belongs_to :author, class_name: 'User'
has_many :comments, dependent: :destroy
scope :published, -> { where.not(published_at: nil).where('published_at <= ?', Time.current) }
scope :draft, -> { where(published_at: nil) }
ActiveRecord scopes for reusable query logic
export interface RetryOptions {
retries: number;
baseMs: number;
maxMs: number;
signal?: AbortSignal;
onRetry?: (attempt: number, delay: number, err: unknown) => void;
Exponential backoff with jitter for retries
module Api
module V1
class UsersController < BaseController
def show
user = User.includes(:profile).find(params[:id])
ETags for conditional requests and caching
class PostsController < ApplicationController
def index
@posts = Post.includes(:author)
.order(created_at: :desc)
.page(params[:page])
.per(10)
Turbo Frames: infinite scroll with lazy-loading frame
package dbutil
import (
"context"
"github.com/jackc/pgconn"
Retry Postgres serialization failures with bounded attempts
Share this code
Here's the card — post it anywhere.