All projects
Backend Engineering

Transactional Email Microservice

Queue-based decoupled microservice for email delivery

PythonRabbitMQSMTPDockerFastAPI

Multiple company products needed to send transactional emails (confirmation, notification, alerts). Each product had its own duplicated implementation.

  • 01Completely decoupling email sending from product business logic
  • 02Ensuring reliable delivery even when the SMTP provider is unavailable
  • 03Supporting dynamic templates without requiring a deployment for each content change

Message queue as the public interface

Producers publish to the queue and are unaffected by SMTP unavailability. The consumer processes at the provider's rate, with automatic retry.

Templates stored separately

Templates in the database allow content changes without deployment. Producers send only the data payload.

Asynchronous delivery means the sender doesn't immediately know if the email was sent. Acceptable for transactional emails where seconds of latency is tolerated.

Python consumer reading from RabbitMQ queue, rendering Jinja2 templates, sending via SMTP with exponential retry. Dead letter queue for persistent failures with operational alerting.

Decoupled microservice with message queue, reused across multiple products without code changes.

  • Dead letter queue is essential — without it, failed emails are silently lost
  • Rate limiting on the consumer prevents SMTP provider bans from burst sending