Building a Custom Email Outreach Platform in a Weekend
Sometimes the best software projects aren't born out of ambitious ideas. They're born out of practical business problems.
A client recently reached out after running into limitations with Mailchimp. Their outreach campaigns were being affected by daily sending restrictions, forcing them to spread email campaigns across multiple days. For a business that relied on timely outbound communication, that wasn't sustainable.
Instead of working around those limitations or paying for another platform, they decided to build a tool tailored to their workflow.
The goal wasn't to compete with Mailchimp or recreate years of product development. It was to build a focused internal application that solved one problem well: sending large email campaigns without unnecessary complexity.
Over the course of a weekend, I designed, built, and deployed a custom email outreach platform from scratch.
Understanding the Requirements
Before writing any code, I wanted to understand exactly what the application needed to do.
The requirements were straightforward. Upload a CSV file containing recipients. Compose rich HTML emails. Send emails through Amazon SES. Track campaign progress. Display a summary when the campaign completed.
Just as important was identifying what wasn't required. There was no need for subscriber management, email templates, automation workflows, scheduling, analytics, A/B testing, CRM features, or multi user support. The application would be used internally by a single team, so adding those features would only increase complexity without delivering value.
Keeping the scope intentionally small made every subsequent engineering decision much easier.
Designing the Architecture
The application consists of two services: a React frontend responsible for composing campaigns and displaying progress, and a Node.js and Express backend responsible for processing campaigns and communicating with Amazon SES.
The flow is simple. A user uploads a CSV file, writes an email, and submits the campaign. The backend validates the request, parses the recipients, begins sending emails through Amazon SES, and immediately returns a campaign ID. The frontend then polls the backend periodically until the campaign completes, displaying progress and the final delivery summary.
This keeps the user interface responsive while allowing email delivery to continue in the background.
Engineering Decisions
One decision I made early was to keep the backend stateless.
Since the client didn't need permanent campaign records or reporting, introducing a database would have added unnecessary operational overhead. Instead, campaign history is stored locally in the browser using localStorage, while the backend only maintains campaign state for the duration of processing.
Another decision was to use polling instead of WebSockets. Campaign progress only needed to be updated every few seconds, making periodic HTTP requests a much simpler solution. It reduced infrastructure complexity while still providing a good user experience.
Responsibility was also clearly divided between the frontend and backend. The frontend handles campaign composition, sender information, file uploads, and user interaction. The backend focuses solely on validation, email processing, and communicating with Amazon SES. Keeping each application responsible for a single concern made both codebases easier to maintain.
Deployment
The frontend is deployed on Vercel, while the backend runs on an Amazon EC2 instance behind Nginx, managed with PM2. HTTPS is handled using Let's Encrypt, and Amazon SES serves as the email delivery provider.
This setup is lightweight, reliable, and easy to operate without introducing unnecessary infrastructure.
Conclusion
What started as a limitation with an existing SaaS product became an opportunity to build a solution that fit the client's workflow exactly.
Rather than trying to recreate a full featured email marketing platform, the project focused on solving a single problem well. The result was a custom outreach platform that the client owns, controls, and can adapt as their needs evolve.
Comments
Post a Comment