SaaS and Marketing Technology
Digital Marketing Automation SaaS
A multi-tenant campaign SaaS that automated audience segments, scheduling, cross-channel delivery, analytics, and agency-client reporting workflows today.

Project overview
A marketing agency needed to plan and measure campaigns across email, SMS, WhatsApp, and paid social without copying audiences and results between multiple products. I led the architecture and implementation of a multi-tenant SaaS platform that centralized client access, segmentation, workflow automation, campaign delivery, and performance reporting.
The application served agency operators, client reviewers, finance staff, and administrators. That required flexible permissions and clear data isolation as much as an efficient campaign builder.
Problem statement
Campaign specialists rebuilt similar workflows for every client and channel. Scheduling details lived in spreadsheets, creative approvals arrived through chat, and reports combined exports with different attribution windows. A late audience update could leave one channel using stale data, while provider rate limits caused bursts to fail unpredictably.
The team needed a system that could coordinate long-running automation reliably, show exactly what would happen before launch, and preserve each tenant's data boundaries. It also needed to absorb provider retries and webhooks without double-sending messages or duplicating metrics.
Solution and architecture
The React and TailwindCSS frontend introduced a reusable workflow builder based on triggers, conditions, delays, and actions. A preview converted every visual workflow into a readable execution plan so reviewers could validate audience rules and timing before activation.
Node.js and Express exposed tenant-aware APIs, while MongoDB stored campaigns, audience definitions, consent records, execution logs, and normalized engagement events. Every query was scoped by tenant at the repository layer. Redis supported cached dashboard aggregates, distributed locks, and rate-limit counters.
BullMQ workers processed scheduled steps independently from web requests. Jobs used deterministic keys so retries remained safe:
await campaignQueue.add("deliver", payload, {
jobId: `${tenantId}:${campaignId}:${contactId}:${stepId}`,
attempts: 5,
backoff: { type: "exponential", delay: 2000 },
});
Channel adapters presented one internal delivery contract for email, SMS, and messaging providers. Each adapter translated provider responses into common delivered, bounced, opened, clicked, or failed events. Signed webhooks entered an append-only event stream before aggregation, making reports reproducible.
What shipped
- Multi-client workspaces with agency, client, analyst, and billing roles.
- Reusable audience segments based on profile and engagement behavior.
- Triggered and scheduled cross-channel workflow automation.
- Approval states for copy, creative, audience, and launch readiness.
- Real-time delivery monitoring with retry and failure queues.
- Attribution dashboards, CSV/PDF exports, and scheduled client reports.
- Subscription, invoice, usage, and channel-cost views.
Outcomes
Reusable templates and synchronized audiences reduced campaign setup time by 70% for frequently repeated programs. Scheduled exports and normalized event data shortened monthly reporting cycles by 35%. Cached dashboard endpoints typically responded in under 200 ms, even while workers processed large delivery batches.
The unified audit trail made it easier to explain who approved a campaign and which audience version was sent. Idempotent jobs reduced accidental duplicate delivery during provider outages, and channel adapters made adding a new delivery provider substantially less invasive.
Key engineering decisions
Campaign definitions became immutable after launch. An editor could clone a running campaign into a new version, but could not silently alter the audience or content associated with historical delivery events. That rule simplified compliance reviews and made performance comparisons meaningful. Consent was evaluated again when a delivery job ran, not only when an audience was first calculated, so recent opt-outs were honored during long workflows.
Provider-specific limits were implemented as distributed token buckets in Redis. Separate queues prevented a slow SMS provider from delaying email or analytics processing. Rather than promising perfectly real-time dashboards, the interface displayed an event watermark and the last complete aggregation interval. These choices favored explainability and reliable recovery over a deceptively simple synchronous design. They also gave support staff precise tools to replay a failed batch without rerunning successful contacts.
Related engineering work
The operational dashboard approach relates to the health marketplace admin panel. For the queue, release, and deployment practices behind reliable delivery, read DevOps automation tools for modern delivery. The broader application architecture is discussed in the future of full-stack development.