You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We have production complaints of OTP emails arriving after the 10-minute expiry (see #183, #184). ePDS's own logs can only ever show when we handed the message to Resend over SMTP — everything after acceptance (Resend internal queueing, recipient-side greylisting, full inboxes) is invisible to us, and Resend's REST API exposes only created_at and a last_event state per email, not per-event timestamps. So send→delivered latency cannot be measured retrospectively; it has to be captured as it happens via webhooks.
Proposal
Add a Resend webhook receiver and persist delivery events, so we can compute per-email delivery latency and alert on delays exceeding the OTP lifetime.
Subscribe to email.sent, email.delivered, email.delivery_delayed, email.bounced, email.failed at resend.com/webhooks.
Payloads carry type, created_at, and data (email_id, to, from, subject).
Persist events into a sqlite table keyed by email_id (auth-service DB or its own).
Metrics:
delivery latency = email.delivered.created_at − email.sent.created_at per email_id; track the fraction exceeding ~8–10 min (OTP expiresIn is 600 s, packages/auth-service/src/better-auth.ts:171)
count of email.delivery_delayed events (temporary delivery failure: greylisting, full inbox) — the prime suspect for late OTP arrivals
Webhook delivery is at-least-once with retries (5 s → 10 h) and events may arrive out of order: dedupe on the svix-id header, sort by created_at.
Verify the Svix signature on incoming requests.
Verify first: Resend docs confirm SMTP-sent emails appear in the emails table, but do not explicitly confirm webhook events fire for SMTP-submitted mail (our sends go via nodemailer SMTP, packages/auth-service/src/email/sender.ts). One test send through production SMTP credentials with a webhook registered settles this before building anything.
Problem
We have production complaints of OTP emails arriving after the 10-minute expiry (see #183, #184). ePDS's own logs can only ever show when we handed the message to Resend over SMTP — everything after acceptance (Resend internal queueing, recipient-side greylisting, full inboxes) is invisible to us, and Resend's REST API exposes only
created_atand alast_eventstate per email, not per-event timestamps. So send→delivered latency cannot be measured retrospectively; it has to be captured as it happens via webhooks.Proposal
Add a Resend webhook receiver and persist delivery events, so we can compute per-email delivery latency and alert on delays exceeding the OTP lifetime.
email.sent,email.delivered,email.delivery_delayed,email.bounced,email.failedat resend.com/webhooks.type,created_at, anddata(email_id,to,from,subject).email_id(auth-service DB or its own).email.delivered.created_at−email.sent.created_atperemail_id; track the fraction exceeding ~8–10 min (OTPexpiresInis 600 s,packages/auth-service/src/better-auth.ts:171)email.delivery_delayedevents (temporary delivery failure: greylisting, full inbox) — the prime suspect for late OTP arrivalsmessage_id↔ nodemailer messageId, and with expired-OTP verification failures (Surface better-auth OTP verification failures (expired vs invalid) in server logs #184), to attribute each expiry complaint to delivery delay vs user behaviour.Implementation notes
svix-idheader, sort bycreated_at.packages/auth-service/src/email/sender.ts). One test send through production SMTP credentials with a webhook registered settles this before building anything.