go 101 lines · 3 tabs

Idempotent Email Sending with a Redis Fingerprint Set in Go

Shared by codesnips Sep 2026
3 tabs
package mailer

import (
	"crypto/sha256"
	"encoding/hex"
	"strings"
)

type Email struct {
	To        string
	Template  string
	DedupeKey string
	Body      string
}

// Fingerprint derives a stable identity for a logically-unique email.
// Body is intentionally excluded so volatile content does not break equality.
func Fingerprint(e Email) string {
	parts := []string{
		strings.ToLower(strings.TrimSpace(e.To)),
		e.Template,
		e.DedupeKey,
	}
	sum := sha256.Sum256([]byte(strings.Join(parts, "\x00")))
	return "email:fp:" + hex.EncodeToString(sum[:])
}
3 files · go Explain with highlit

This snippet shows a small, focused pattern for preventing duplicate outbound emails when the same send request can arrive more than once — a common problem with at-least-once queues, retried HTTP handlers, and re-run cron jobs. The core idea is to compute a stable fingerprint for each email and record it in a Redis set (technically a set of keys with TTL) so that a second attempt with the same fingerprint is skipped before the message ever reaches the SMTP provider.

In the fingerprint tab, Fingerprint derives a deterministic key from the fields that define a logically-identical email: recipient, template, and a caller-supplied DedupeKey. Using DedupeKey rather than the full rendered body matters because bodies often contain timestamps or tracking pixels that would break equality; the caller decides what "the same email" means. The value is hashed with SHA-256 and hex-encoded so the Redis key stays fixed-length and safe regardless of address length.

The Deduper tab wraps the actual guard. Reserve uses SET key value NX PX ttl, which atomically claims the fingerprint only if it does not already exist. This single round-trip is the crux of the pattern: the check and the claim happen together, so two concurrent workers cannot both pass the guard. A true return means this caller won the race and should send; false means another attempt already reserved it. Release exists for the failure path — if sending errors out, the reservation is deleted so a legitimate retry can proceed rather than being silently swallowed.

The Mailer tab ties it together. Send computes the fingerprint, calls Reserve, and short-circuits with ErrDuplicate when the slot is taken. Crucially it uses defer with a flag so that if smtp.Send fails, Release is called and the fingerprint is freed. The chosen TTL is a deliberate trade-off: long enough to cover realistic retry windows and duplicate bursts, short enough that Redis memory does not grow unbounded and that a genuinely-new email after the window is not blocked. Callers that need stronger guarantees can persist fingerprints in sql instead, but Redis keeps the hot path fast.


Related snips

Share this code

Here's the card — post it anywhere.

Idempotent Email Sending with a Redis Fingerprint Set in Go — share card
Link copied