PropSpaceX Mail Service

Asynchronous notification microservice — RabbitMQ job queues with retries and dead-letter handling, template rendering, and SMTP delivery via Nodemailer.

Node.jsExpressRabbitMQNodemailerMongoDBgRPC
GitHub
01

System Architecture

REQUESTgRPC sendMail(template, payload)tracing
publishconsumemax retriesrendersendlogInternal ServicesPayment · User · PropertyEDGEgRPC APIJob intakeSVCRabbitMQJob queueQUEUEDead Letter QueueFailed after retriesQUEUEWorker PoolBackoff · throttlingSVCTemplate EngineLocalized renderingSVCNodemailerSMTP deliveryEXTMongoDBDelivery logs · TTLDATA

Services publish mail jobs over gRPC into RabbitMQ. Workers consume with exponential backoff, render templates, and deliver via Nodemailer/SMTP. Exhausted retries land in a dead-letter queue; every attempt is logged to MongoDB.

02

Database Design

SCHEMA3 tables · 2 relationshover a table
templatesMongoDB_idobjectIdnamestringsubjectstringlocalestringbody_htmlstringversionnumberemail_jobsMongoDB_idobjectIdtemplate_idobjectIdrecipientstringpayloadobjectstatusenumattemptsnumbernext_retry_atdatedelivery_logsMongoDB_idobjectIdjob_idobjectIdstatusenumprovider_msg_idstringattempted_atdate

Jobs reference versioned templates; each delivery attempt is logged separately so bounces and retries stay auditable.

03

Engineering Challenges

01

Guaranteed delivery

Exponential backoff with dead-letter queues means a transactional email is never silently dropped.

02

Template management

Versioned, localized templates rendered at send time from job payloads.

03

Provider rate limits

Queue throttling keeps outbound volume inside SMTP provider limits during spikes.

04

Bounce handling

Webhook processing for bounces and complaints protects sender reputation automatically.

04

Trade-offs & Decisions

ChoseOverBecause
RabbitMQRedis queueAcknowledgements, redelivery, and DLQs are first-class — exactly what transactional mail needs.
gRPC intakeRESTMail is triggered from other services on the request path; low-latency internal calls matter.
NodemailerProvider SDKSMTP keeps the service provider-agnostic — switching ESPs is a config change.