Email campaigns were going out on fixed schedules to everyone, regardless of where users were in their journey or what actions they had taken. Engagement was low — the right message was not reaching people at the right time.
The core shift was from time-based to event-based triggering.
Instead of send this email every Tuesday, the system listens for user actions — sign-up, product view, abandoned cart, first purchase — and triggers the appropriate email based on that event. Built a lightweight event listener and rules engine mapping events to templates and delays.
class TriggerEngine:
RULES = {
'user.signup': ('welcome', delay=0),
'product.viewed': ('follow_up', delay=3600),
'cart.abandoned': ('recovery', delay=7200),
'order.completed': ('receipt', delay=0),
}
def handle_event(self, event: str, user_id: str):
if event not in self.RULES:
return
template, delay = self.RULES[event]
# Idempotency — cooldown per user per event
if self.in_cooldown(user_id, event):
return
self.schedule_email(
user_id=user_id,
template=template,
send_at=now() + delay
)
self.set_cooldown(user_id, event)SMTP at scale is a reliability and deliverability problem. SendGrid handles bounce management, unsubscribes, and deliverability reputation. Integrated their API with full suppression list checking on every send.
Marketing teams can adjust which events trigger which emails without touching code. Deliberate design choice: the system should outlast any single engineer.
Campaigns became targeted and contextually relevant. Marketing teams can evolve campaigns without engineering involvement each time.
"People were getting messages that matched where they actually were in their journey, not generic blasts."