Please hold on for a moment while the content loads.
Please hold on for a moment while the content loads.
Centralized Email Platform
Production email platform forked from open-source Plunk, extended with a custom BullMQ worker and Redis-backed queue, with delivery routed through AWS SES. Replaced Mailgun for transactional emails, campaigns, and workflow automation. Significant cost reduction vs Mailgun with comparable delivery performance.
A centralized email platform built on an open-source core to eliminate per-provider costs and unify delivery across multiple product teams. The system handles transactional emails, marketing campaigns, and automated workflows through a queue-based architecture with real-time delivery tracking.

Run the platform for 5+ product teams: monitoring, delivery health, incident response, and release coordination across services.
Extend the Plunk fork with custom capabilities: BullMQ worker, rate limiting, bounce/complaint processing, and delivery failure handling.
Own template management and delivery changes that touch multiple product teams with independent release schedules. Handle upstream sync of the fork.
Simplicity, observability, and dependable delivery first the queue absorbs spikes, retries with backoff, and every failure mode has a defined recovery path.
High-level system architecture showing request flow from clients through queue to delivery
Delivery failure retry strategy with exponential backoff and dead letter queue
API-driven email delivery with template support and variable substitution for automated notifications.
Newsletter and product update delivery to segmented audiences with open and click tracking.
Redis-backed job queue with configurable concurrency, rate limiting, and automatic retries.
Verified sending domains with DKIM and SPF configuration for deliverability.
Automated phishing detection via LLM integration with configurable sample rates and thresholds.
Multi-step automations with triggers, delays, and conditional logic for complex email sequences.
Options evaluated: self-hosted Postfix (operational overhead of SPF/DKIM monitoring, IP reputation management), direct AWS SES (template management complexity, sandbox limitations for a small team), and Plunk as a managed layer on top of SES/Postmark.
Chose Plunk for operational simplicity and built-in analytics. Trade-off: at very high volumes (>1M/day), Plunk's per-email cost may exceed direct SES pricing. Planned migration path: move to direct SES if volume exceeds Plunk cost-efficiency threshold while keeping the platform architecture intact.
Email delivery, campaign processing, and workflow execution are I/O-bound operations that shouldn't block API responses. Needed backpressure handling for volume spikes.
Separate worker process processes jobs asynchronously with configurable concurrency and rate limiting. Workers can scale independently from the API server. Queue provides natural backpressure during spikes.
// BullMQ worker with configurable concurrency and rate limiting.
// Workers scale independently from the API server.
const emailQueue = new Queue("email-delivery", {
connection: redisConfig,
defaultJobOptions: {
attempts: 5,
backoff: { type: "exponential", delay: 1000 },
removeOnComplete: { count: 1000 },
removeOnFail: { count: 5000 },
},
})
const worker = new Worker("email-delivery", processEmailJob, {
connection: redisConfig,
concurrency: 10,
limiter: { max: 100, duration: 1000 },
})
worker.on("failed", (job, err) => {
logger.error("Email delivery failed", {
jobId: job.id,
attempt: job.attemptsMade,
error: err.message,
})
})Building a production email platform from scratch would have taken months. An open-source alternative provided a solid foundation with active community maintenance.
Forked an existing platform and added custom integrations while maintaining upstream sync. Fork maintenance cost: monthly merge conflicts and upstream API changes require dedicated sync cycles.
Background job processing can be resource-intensive and should not degrade API response times. A crash in the worker should not affect API availability.
Worker process runs independently, enabling independent scaling and fault isolation. If the worker crashes, the API server remains unaffected. Monitoring alerts on worker health.
Transient failures (rate limits, provider outages, network blips) are common in email delivery. Naive retries cause thundering herd problems on recovery.
Exponential backoff with random jitter spreads retries across time, preventing thundering herd. Maximum delay capped at 30 seconds with 5 retry attempts.
// Exponential backoff with jitter: prevents thundering herd on recovery.
async function retryWithBackoff<T>(
fn: () => Promise<T>,
opts: { maxAttempts: number; baseDelay: number; maxDelay: number },
): Promise<T> {
for (let attempt = 0; attempt < opts.maxAttempts; attempt++) {
try {
return await fn()
} catch (err) {
if (attempt === opts.maxAttempts - 1) throw err
const delay = Math.min(
opts.baseDelay * Math.pow(2, attempt) + Math.random() * 1000,
opts.maxDelay,
)
logger.warn("retry after failure", {
attempt,
delay,
error: (err as Error).message,
})
await new Promise(r => setTimeout(r, delay))
}
}
throw new Error("unreachable")
}Moving transactional, campaign, and workflow email off Mailgun and onto PH Mailer cut email-sending cost by roughly 50–60% at comparable delivery performance. Exact figures are confidential to the organization.
A monitored batch run processed 48,978 queued items in 5 minutes 35 seconds roughly 146 emails per second sustained, with 48,965 delivered, 112 transient exceptions handled by retry, and 26 bounces routed to the suppression list. These numbers come from the monitoring alert on this page: real production run, not a synthetic load test.
Each service runs as a Docker container, deployed through a versioned pipeline: build → test → push image → staged rollout on UAT → health check → rolling update on production, with the previous image retained for instant rollback. UAT validates upstream Plunk syncs before they reach production, which matters because we maintain a fork.
Versioned deploy pipeline: build → test → image → UAT → health check → rolling update with rollback
The worker logs processed/sent/exception/bounce counters per batch run, and Uptime Kuma surfaces a Discord alert with the summary (shown in the Observability section). This gives a delivery health check on every batch a spike in exceptions or bounces trips an alert before users notice.
The 'Forgot Password' functionality stopped working because the SMTP server was not configured. Users were unable to receive password reset emails, blocking their ability to regain account access.
To unblock users immediately, I queried the reset token directly from the Redis server, manually constructed the password reset URL, and shared it with the team. This allowed affected users to reset their passwords while the SMTP configuration was being fixed.
The SMTP server configuration was missing from the deployment environment. The email system was successfully queuing messages but failing to deliver them because no outbound mail server was configured.
This incident highlighted the need for delivery monitoring. Without it, queued emails can silently fail. Added health checks for outbound integrations and configured delivery failure alerts.
Rapid initial development, community support, upstream features
Monthly merge conflicts, upstream API changes, fork synchronization overhead
Optimal throughput based on provider quota, adaptive to account health
Quota fetch on startup adds latency, worker count changes require restart
API stays responsive, retries are automatic, queue provides backpressure
Eventual delivery, queue management overhead, dead letter handling
Delivery Provider Quota Exceeded
Emails fail to send, queue backs up
Rate limiter dynamically adjusts throughput based on provider health. Queue provides backpressure instead of dropping requests. Alert triggers when queue depth exceeds threshold.
Worker Process Crash
Email processing stops, API stays responsive
Process manager auto-restarts worker. Queue preserves unprocessed jobs. Alert on worker process disappearance.
Redis Outage
Queue unavailable, new jobs cannot be enqueued
API returns 503 during Redis unavailability. Jobs already in queue are preserved on restart (persistent Redis config). Alert on Redis connectivity loss.
Bounce / Complaint Spike
SES reputation drops, sending quotas reduced
Automated bounce processing suppresses repeated bounces. Complaint feedback loop updates suppression list. Dashboard monitors bounce rate trends.
Upstream API Breaking Change (Fork)
Platform features may break during sync
Isolate custom code in separate files to reduce merge conflicts. UAT environment validates sync before production. Staged rollouts for upstream updates.

Individual modules: template rendering, webhook handlers, queue job processors
Vitest with mocked external dependencies. Tests cover edge cases: malformed templates, webhook signature mismatch, queue job serialization errors.
API endpoints with real database, queue interaction with Redis
Testcontainers for PostgreSQL and Redis in CI. Tests verify: email submission → queue → worker → delivery provider mock. Database migrations are tested in isolation.
Critical user flows: password reset, campaign delivery, bounce handling
Full workflow tests in UAT environment with real delivery provider sandbox. Tests cover: template rendering, delivery tracking, bounce feedback loop.
Bootcamp platform backend: 35 Vitest unit/service tests covering analytics, enrollment, bKash payments, course management, user services, and activity logging
Vitest with mocked database queries. CI runs on every push via GitHub Actions. Test files: src/services/__tests__/*.test.ts, src/utils/__tests__/*.test.ts
Silent failures in email delivery are invisible without proper monitoring. Every outbound integration needs health checks.
Without a queue, email volume spikes would degrade API performance. BullMQ provides natural backpressure and retry logic.
Maintaining a fork requires discipline: isolating custom code in separate files reduces merge conflicts during upstream sync.
Using Redis data directly to unblock users was faster than fixing the SMTP config. Sometimes operational workarounds are the right call.
This is a proprietary production system. The details above reflect my actual work. Additional evidence available upon request:
Contact me to arrange verification under NDA.