i've now built the "send transactional email when X happens to a user" pipeline three different ways across three projects. each works. each has a regime where it's correct. writing this up because i kept hitting the same decision and re-figuring it out.
pattern 1: postgres trigger + pg_net
trigger on auth.users update fires when confirmed_at flips from null to a timestamp. the trigger inserts a row in an email_queue table. a pg_cron job every minute reads the queue and calls resend (or postmark, sendgrid, whatever) via pg_net.
good for:
friction:
pattern 2: auth send-email hook
shipped in 2024, still the right tool for emails that are part of the auth flow itself. signup, magic link, password reset, email change. you register an edge function as the send-email hook, supabase calls it instead of using the default smtp, you decide what to send.
good for:
friction:
pattern 3: external tool that watches the database
The user shares their experience implementing transactional email pipelines using three different methods: Postgres triggers with pg_net, auth send-email hooks, and external tools. They discuss the pros and cons of each approach and provide guidance on when to use each method based on specific use cases and constraints.
Super helpful content, thank you!
AI slop that lower() was called on
something subscribes to auth.users changes (database webhook, or polls raw_app_meta_data on a schedule) and triggers the email externally. customer.io, loops.so, dreamlit, segment in front of any of them. trade is real: you're shipping user state outside your db, and another vendor in your dependency graph.
good for:
friction:
how i actually choose
honestly: pick the boring one that matches the actual constraint. all three are fine.
anyone in here split between two patterns and want to compare notes? specifically curious about people running auth hooks + trigger-based business emails on the same project — does the operational overhead of two pipelines actually pay off?