Skip to main content
Twilio SendGrid is the production mailer provider: it delivers transactional emails via the SendGrid HTTP API and validates delivery with a status-code check on every send.

Built-in templates

The mailer ships five transactional templates out of the box. Both the SendGrid and local providers render all of them:
TemplateTrigger
VERIFY_EMAILNew user registration — prompts email confirmation
LOST_PASSWORDUser initiates a forgotten-password flow
PASSWORD_RESETConfirmation after a successful password reset
ORGANIZATION_INVITATIONMember invited to join an organisation
WELCOMEFirst sign-in after email verification
Template source files live in apps/backend/src/tools/mailer/emails/.

Sending vs queuing

The MailerType contract exposes two methods:
MethodHowWhen to use
tools.mailer.send()Delivers immediately and synchronouslyWebhooks, admin triggers, tests
tools.mailer.queue()Enqueues onto the EMAIL queueEverything else — keeps the request fast
Never call send() from inside the EMAIL queue consumer — it causes an infinite loop.

Why

SendGrid is a reliable, scalable email delivery service with detailed delivery analytics, bounce handling, and suppression list management. It’s the right choice for production transactional email — API key setup takes under five minutes and the SDK handles retries at the HTTP layer.

Setup

  1. In apps/backend/src/configuration/production.ts, set tools.mailer:
    mailer: {
      client: MailerClientType.TWILIO_SENDGRID,
      from: 'noreply@yourdomain.com',
    }
    
  2. In your production environment, set:
    SENDGRID_API_KEY=SG.your_api_key_here
    
  3. Keep development.ts and test.ts using the local client.
  4. Run make test module=backend.

Adding a new email template

  1. Create apps/backend/src/tools/mailer/emails/<templateName>.ts. Export a <TemplateName>TemplateAttributes type and a render function that returns { to, from, subject, html }.
  2. Add the template key to AvailableTemplates in apps/backend/src/tools/mailer/emails/index.ts and register the render function in the templates map.
  3. Add a case AvailableTemplates.<YOUR_TEMPLATE> in the send switch inside apps/backend/src/tools/mailer/twilioSendgrid.ts and apps/backend/src/tools/mailer/local.ts.
  4. Export the new TemplateAttributes type from apps/backend/src/tools/mailer/index.ts.
  5. Write a test in apps/backend/src/tools/mailer/emails/__tests__/<templateName>.spec.ts.
  6. Run make test module=backend.

Gotchas

  • SENDGRID_API_KEY must be set at server startup. A missing key throws immediately inside buildTwilioSendgridMailer before any emails are attempted.
  • SendGrid returns HTTP 202 for accepted messages — the implementation throws if it receives anything else. Check logs if emails go missing.
  • The queue method enqueues onto the EMAIL queue. The consumer that processes that queue calls send — never call send again from inside the consumer.
  • Domain authentication in SendGrid (DKIM/SPF) is required to avoid spam folder placement. Configure it in the SendGrid dashboard before going to production.

What’s next?