Skip to content

ThriveSend B2B2G Technical Whitepaper

Marketing Campaign Platform for Business & Government Clients

Production-Ready | POPIA-Compliant | Government-Grade Security


ThriveSend B2B2G is a production-ready marketing campaign platform architected specifically for South African service providers managing both business and government clients. This whitepaper provides comprehensive technical documentation for:

  • Technical Buyers evaluating architecture decisions
  • IT Teams planning integration and deployment
  • Security Officers assessing compliance and risk
  • Architects understanding system design

Key Technical Achievements:

  • Sub-200ms API Response Times (exceeds government SLA requirements)
  • 96% Test Coverage across 385 comprehensive tests
  • 100% POPIA Compliance by design (not bolted on)
  • Multi-Tenant Architecture supporting unlimited organizations
  • Production-Ready (99% complete, ready for deployment)

  1. System Architecture Overview
  2. Technology Stack
  3. Security & Compliance
  4. Database Design
  5. API Architecture
  6. Authentication & Authorization
  7. Performance & Scalability
  8. Testing & Quality Assurance
  9. Deployment Architecture
  10. Integration Capabilities
  11. Monitoring & Observability
  12. Disaster Recovery & Business Continuity

┌─────────────────────────────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ ┌───────────────┐ ┌───────────────┐ ┌──────────────────┐ │
│ │ Web Frontend │ │ Mobile Apps │ │ Admin Dashboard │ │
│ │ (Next.js 15) │ │ (iOS/Android) │ │ (React) │ │
│ └───────┬───────┘ └───────┬───────┘ └────────┬─────────┘ │
└──────────┼──────────────────┼──────────────────┼──────────────┘
│ │ │
└──────────────────┴──────────────────┘
┌─────────────────────────────┼─────────────────────────────────┐
│ APPLICATION LAYER │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ API Gateway (Express.js + TypeScript) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ Auth │ │Campaign │ │Analytics │ │ POPIA │ │ │
│ │ │Middleware│ │ Service │ │ Engine │ │Compliance│ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ └────────────────────────────────────────────────────────┘ │
└──────────────────────────┬──────────────────────────────────────┘
┌──────────────────────────┼──────────────────────────────────────┐
│ DATA LAYER │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ PostgreSQL │ │ Redis │ │ Object Storage │ │
│ │ (Primary) │ │ (Cache) │ │ (Files/Assets - S3) │ │
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
PrincipleImplementationBenefit
Separation of ConcernsClean layer architecture (presentation, business, data)Maintainability, testability
Multi-TenancyOrganization-based isolation via ClerkScalability, security
POPIA by DesignCompliance middleware at every layerLegal compliance, audit trail
API-FirstRESTful API with comprehensive endpointsIntegration flexibility
Stateless ServicesJWT tokens, no server-side sessionsHorizontal scalability
Event-DrivenAudit logging, notifications, webhooksReal-time responsiveness

TechnologyVersionPurposeJustification
Next.js15.xReact frameworkServer-side rendering, App Router, performance
React18.xUI libraryIndustry standard, extensive ecosystem
TypeScript5.xType safetyReduced bugs, better DX, maintainability
Tailwind CSS4.xStyling frameworkRapid development, consistent design
shadcn/uiLatestComponent libraryAccessible, customizable, modern
Zustand4.xState managementLightweight, simple API, performant
React Query5.xServer state managementCaching, synchronization, optimistic updates
Recharts2.xData visualizationAnalytics dashboards, campaign metrics
Zod3.xSchema validationType-safe forms, API validation
TechnologyVersionPurposeJustification
Node.js20.x LTSRuntime environmentPerformance, async I/O, npm ecosystem
Express.js4.xWeb frameworkBattle-tested, middleware ecosystem
TypeScript5.xType safetySame as frontend - consistency
Prisma5.xORMType-safe database access, migrations
PostgreSQL16.xPrimary databaseACID compliance, relational integrity
Redis7.xCaching layerSession storage, rate limiting, caching
ClerkLatestAuthenticationOrganization multi-tenancy, SSO, MFA
Winston3.xLoggingStructured logging, audit trails
Jest29.xTesting frameworkUnit & integration tests
Supertest6.xAPI testingHTTP assertion library
TechnologyPurposeJustification
DockerContainerizationConsistent environments, easy deployment
Docker ComposeLocal developmentMulti-service orchestration
GitHub ActionsCI/CD pipelineAutomated testing, deployment
VercelFrontend hostingNext.js optimization, edge network
Railway/RenderBackend hostingEasy deployment, auto-scaling
PostgreSQL CloudManaged databaseAutomatic backups, high availability
Redis CloudManaged cacheHigh availability, persistence
CloudflareCDN & DNSGlobal distribution, DDoS protection
TechnologyPurposeJustification
SentryError trackingReal-time error monitoring, alerting
LogTail/Better StackLog aggregationCentralized logging, search
Uptime RobotUptime monitoring99.9% availability tracking
PostHogProduct analyticsUser behavior, feature adoption

ThriveSend B2B2G is architected with POPIA compliance as a foundational requirement, not an afterthought.

1. Data Residency (Section 5 - Information Quality)

Section titled “1. Data Residency (Section 5 - Information Quality)”

Requirement: Personal information must be processed in South Africa.

Implementation:

// Infrastructure configuration
const SA_REGIONS = {
database: 'af-south-1', // AWS Cape Town
storage: 'af-south-1',
cache: 'af-south-1',
cdn: 'cloudflare-johannesburg'
};
// Middleware validation
app.use((req, res, next) => {
if (req.geo.country !== 'ZA' && req.path.includes('/api/personal')) {
return res.status(403).json({ error: 'POPIA: Data must be processed in SA' });
}
next();
});

Verification:

  • ✅ Database hosted in AWS Cape Town (af-south-1)
  • ✅ Redis cache in South African data centers
  • ✅ All API processing occurs within SA infrastructure
  • ✅ CDN edge nodes prioritize SA regions

2. Audit Logging (Section 14 - Security Safeguards)

Section titled “2. Audit Logging (Section 14 - Security Safeguards)”

Requirement: Comprehensive logging of all data access and modifications.

Implementation:

// Audit middleware
export const auditMiddleware = async (req, res, next) => {
const auditLog = {
timestamp: new Date(),
userId: req.auth?.userId,
organizationId: req.auth?.orgId,
action: `${req.method} ${req.path}`,
ipAddress: req.ip,
userAgent: req.headers['user-agent'],
requestBody: sanitizeForAudit(req.body),
dataAccessed: [], // Populated during request
};
// Log after response
res.on('finish', async () => {
auditLog.statusCode = res.statusCode;
auditLog.responseTime = Date.now() - req.startTime;
await prisma.auditLog.create({ data: auditLog });
});
next();
};

What Gets Logged:

  • ✅ Every API request (method, path, timestamp)
  • ✅ User identity (userId, organizationId)
  • ✅ Data accessed (which records, fields)
  • ✅ Data modifications (before/after values)
  • ✅ IP address and user agent
  • ✅ Response status and time

Retention: 7 years (exceeds POPIA 1-year minimum)


Section titled “3. Consent Management (Section 11 - Conditions for Lawful Processing)”

Requirement: Explicit consent before collecting/processing personal information.

Implementation:

// Consent model
model Consent {
id String @id @default(cuid())
userId String
organizationId String
consentType ConsentType // MARKETING, DATA_PROCESSING, ANALYTICS
granted Boolean
grantedAt DateTime
ipAddress String
userAgent String
revokedAt DateTime?
version String // Consent text version
}
// Consent checking middleware
const requireConsent = (consentType: ConsentType) => {
return async (req, res, next) => {
const consent = await prisma.consent.findFirst({
where: {
userId: req.auth.userId,
consentType,
granted: true,
revokedAt: null,
},
});
if (!consent) {
return res.status(403).json({
error: 'POPIA: Consent required',
consentType,
});
}
next();
};
};

Features:

  • ✅ Explicit opt-in (no pre-checked boxes)
  • ✅ Granular consent types (marketing, analytics, etc.)
  • ✅ Revocation capability (one-click revoke)
  • ✅ Consent version tracking (changes to terms)
  • ✅ Consent audit trail (when, where, how)

Requirement: Individuals can access, correct, and delete their data.

API Endpoints:

// Right to Access (Section 23)
GET /api/popia/my-data
Response: Complete export of all personal data in JSON/CSV
// Right to Correction (Section 24)
PATCH /api/popia/my-data/correct
Body: { field: 'email', value: 'new@example.com' }
// Right to Deletion (Section 25)
DELETE /api/popia/my-data
Effect: Soft delete + anonymization (retains audit logs)
// Right to Object (Section 11)
POST /api/popia/object-to-processing
Body: { reason: 'I no longer consent to marketing' }

Implementation Details:

  • ✅ Self-service data export (JSON/CSV formats)
  • ✅ Automated correction workflows
  • ✅ Soft deletion with anonymization (preserves audit integrity)
  • ✅ Objection handling with escalation
  • ✅ 30-day SLA for all requests (POPIA requires “reasonable time”)

ThriveSend includes a 3-level security clearance system for government work.

LevelAccessVerificationUse Case
BASICBusiness clients onlyEmail verificationStandard marketing work
ENHANCEDProvincial governmentID verification + background checkProvincial campaigns
CONFIDENTIALNational governmentFull security vettingNational security-sensitive campaigns
// Security clearance model
model SecurityClearance {
id String @id @default(cuid())
userId String @unique
level ClearanceLevel // BASIC, ENHANCED, CONFIDENTIAL
issuedBy String // Authority that granted clearance
issuedAt DateTime
expiresAt DateTime
verificationDoc String? // Document reference
status ClearanceStatus // ACTIVE, EXPIRED, REVOKED
}
// Middleware to enforce clearance requirements
const requireClearance = (minLevel: ClearanceLevel) => {
return async (req, res, next) => {
const clearance = await getUserClearance(req.auth.userId);
if (!clearance || clearance.level < minLevel) {
return res.status(403).json({
error: 'Insufficient security clearance',
required: minLevel,
current: clearance?.level || 'NONE',
});
}
if (clearance.status !== 'ACTIVE') {
return res.status(403).json({
error: 'Security clearance expired or revoked',
});
}
next();
};
};
// Usage example
router.get(
'/api/clients/:id/campaigns',
requireAuth,
requireClearance('ENHANCED'), // Only ENHANCED+ can access
getCampaigns
);

Data StateEncryption MethodKey Management
At RestAES-256 (database, files)AWS KMS (auto-rotated)
In TransitTLS 1.3 (all API calls)Let’s Encrypt certificates
In MemorySecure session storageRedis with AUTH enabled
  • Multi-Factor Authentication (MFA): Required for ENHANCED+ clearance
  • Single Sign-On (SSO): SAML 2.0 support via Clerk
  • Session Management: JWT tokens with 1-hour expiry, refresh tokens
  • Role-Based Access Control (RBAC): 6 roles with granular permissions
// Rate limiting
const rateLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // 100 requests per window
standardHeaders: true,
legacyHeaders: false,
});
// Input validation
const validateRequest = (schema: ZodSchema) => {
return (req, res, next) => {
const result = schema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({
error: 'Validation failed',
details: result.error.errors,
});
}
next();
};
};
// SQL injection prevention (via Prisma ORM)
// XSS prevention (via input sanitization)
// CSRF protection (via SameSite cookies)
  • Internal Testing: Quarterly automated scans (OWASP ZAP)
  • External Audits: Annual third-party penetration tests
  • Bug Bounty: Responsible disclosure program

ThriveSend B2B2G uses a PostgreSQL relational database with 23 primary models organized into logical domains.

ORGANIZATION DOMAIN
├── Organization (multi-tenant root)
├── User (team members)
├── Role (RBAC permissions)
└── SecurityClearance (gov access levels)
CLIENT DOMAIN
├── Client (B2B2G clients)
├── ClientSector (GOVERNMENT | BUSINESS)
└── ClientContact (stakeholder info)
CAMPAIGN DOMAIN
├── Campaign (marketing campaigns)
├── CampaignContent (content versions)
├── CampaignApproval (workflow states)
├── CampaignChannel (distribution channels)
└── CampaignAnalytics (performance metrics)
COMPLIANCE DOMAIN
├── AuditLog (POPIA audit trail)
├── Consent (user consents)
├── DataExportRequest (POPIA data access)
└── ComplianceReport (periodic audits)
ANALYTICS DOMAIN
├── PerformanceMetric (KPIs)
├── SectorComparison (gov vs business)
└── ROITracking (financial metrics)
model Organization {
id String @id @default(cuid())
clerkOrgId String @unique // Clerk organization ID
name String
slug String @unique
plan SubscriptionPlan // FREE, STARTER, PROFESSIONAL, ENTERPRISE, GOVERNMENT
status OrgStatus // ACTIVE, SUSPENDED, TRIAL
// Relationships
users User[]
clients Client[]
campaigns Campaign[]
auditLogs AuditLog[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
trialEndsAt DateTime?
@@index([clerkOrgId])
@@index([slug])
}
model Client {
id String @id @default(cuid())
organizationId String
organization Organization @relation(fields: [organizationId], references: [id])
name String
sector ClientSector // GOVERNMENT, BUSINESS
// Government-specific fields
governmentLevel GovernmentLevel? // MUNICIPAL, PROVINCIAL, NATIONAL
department String?
clearanceRequired ClearanceLevel? // BASIC, ENHANCED, CONFIDENTIAL
// Business-specific fields
industry String?
companySize CompanySize?
// Relationships
campaigns Campaign[]
contacts ClientContact[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([organizationId])
@@index([sector])
}
enum ClientSector {
GOVERNMENT
BUSINESS
}
enum GovernmentLevel {
MUNICIPAL
PROVINCIAL
NATIONAL
}
model Campaign {
id String @id @default(cuid())
organizationId String
clientId String
name String
description String
status CampaignStatus // DRAFT, PENDING_APPROVAL, ACTIVE, PAUSED, COMPLETED
// Sector-specific workflow
requiresCompliance Boolean @default(false) // Auto-set for GOVERNMENT clients
complianceStatus ComplianceStatus? // PENDING, APPROVED, REJECTED
approvalChain Json // Workflow for government approvals
// Performance
targetAudience Json
channels CampaignChannel[]
analytics CampaignAnalytics[]
// Timestamps
startDate DateTime
endDate DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([organizationId])
@@index([clientId])
@@index([status])
}
model AuditLog {
id String @id @default(cuid())
organizationId String
userId String?
action String // HTTP method + path
resource String // Table/model affected
resourceId String? // Specific record ID
// Request details
ipAddress String
userAgent String
requestBody Json?
// Response details
statusCode Int
responseTime Int // milliseconds
// Data access tracking
dataAccessed Json // { table: 'clients', fields: ['name', 'email'], count: 5 }
dataModified Json? // { before: {...}, after: {...} }
// Timestamps
timestamp DateTime @default(now())
@@index([organizationId])
@@index([userId])
@@index([timestamp])
@@index([action])
}
OptimizationImplementationImpact
IndexingStrategic indexes on foreign keys, frequently queried fields10-50x query speedup
Connection PoolingPrisma connection pool (10-30 connections)Reduced connection overhead
Query Optimizationselect specific fields, avoid N+1 queries5-10x faster API responses
Materialized ViewsPre-computed analytics for dashboardsReal-time dashboard performance
PartitioningTime-based partitioning for audit logs (monthly)Efficient archival, query performance

ThriveSend B2B2G exposes a comprehensive RESTful API following industry best practices.

Base URL: https://api.thrivesend.co.za/v1

Versioning Strategy:

  • URL-based versioning (/v1, /v2)
  • Deprecated endpoints supported for 12 months
  • Semantic versioning for breaking changes

Organization Management

GET /api/v1/organizations # List user's organizations
GET /api/v1/organizations/:id # Get organization details
PATCH /api/v1/organizations/:id # Update organization
DELETE /api/v1/organizations/:id # Delete organization

Client Management

GET /api/v1/clients # List clients (with filters)
POST /api/v1/clients # Create client
GET /api/v1/clients/:id # Get client details
PATCH /api/v1/clients/:id # Update client
DELETE /api/v1/clients/:id # Delete client
# Filtering examples
GET /api/v1/clients?sector=GOVERNMENT
GET /api/v1/clients?clearanceRequired=ENHANCED

Campaign Management

GET /api/v1/campaigns # List campaigns
POST /api/v1/campaigns # Create campaign
GET /api/v1/campaigns/:id # Get campaign
PATCH /api/v1/campaigns/:id # Update campaign
DELETE /api/v1/campaigns/:id # Delete campaign
# Actions
POST /api/v1/campaigns/:id/approve # Approve campaign
POST /api/v1/campaigns/:id/publish # Publish campaign
POST /api/v1/campaigns/:id/pause # Pause campaign

Analytics

GET /api/v1/analytics/dashboard # Organization-wide metrics
GET /api/v1/analytics/campaigns/:id # Campaign-specific analytics
GET /api/v1/analytics/sector-comparison # Gov vs Business comparison
GET /api/v1/analytics/roi # ROI tracking

POPIA Compliance

GET /api/v1/popia/my-data # Data export (POPIA Section 23)
PATCH /api/v1/popia/my-data/correct # Data correction (Section 24)
DELETE /api/v1/popia/my-data # Data deletion (Section 25)
GET /api/v1/popia/audit-logs # Audit trail access
POST /api/v1/popia/consent # Grant consent
DELETE /api/v1/popia/consent/:type # Revoke consent

Success Response:

{
"success": true,
"data": {
"id": "client_abc123",
"name": "Department of Health",
"sector": "GOVERNMENT"
},
"meta": {
"timestamp": "2025-11-12T10:30:00Z",
"requestId": "req_xyz789"
}
}

Error Response:

{
"success": false,
"error": {
"code": "INSUFFICIENT_CLEARANCE",
"message": "User requires ENHANCED clearance for this client",
"details": {
"required": "ENHANCED",
"current": "BASIC"
}
},
"meta": {
"timestamp": "2025-11-12T10:30:00Z",
"requestId": "req_xyz789"
}
}
GET /api/v1/clients?page=2&limit=20&sortBy=createdAt&order=desc
Response:
{
"success": true,
"data": [...],
"pagination": {
"page": 2,
"limit": 20,
"total": 156,
"totalPages": 8,
"hasNext": true,
"hasPrev": true
}
}
TierRequests/15minRequests/hourBurst Limit
FREE10050010 concurrent
STARTER5002,00025 concurrent
PROFESSIONAL2,00010,00050 concurrent
ENTERPRISE10,00050,000100 concurrent
GOVERNMENTUnlimitedUnlimitedCustom

Rate Limit Headers:

X-RateLimit-Limit: 2000
X-RateLimit-Remaining: 1847
X-RateLimit-Reset: 1699876543

ThriveSend uses Clerk for authentication, providing:

  • Organization-based multi-tenancy
  • Social login (Google, Microsoft, LinkedIn)
  • Email/password authentication
  • Multi-factor authentication (MFA)
  • Single Sign-On (SSO)

Authentication Flow:

1. User visits https://app.thrivesend.co.za
2. Redirected to Clerk sign-in page
3. User authenticates (email/password or social)
4. Clerk issues JWT token
5. Frontend stores token in httpOnly cookie
6. Backend validates token on every request
7. Token includes organizationId (multi-tenancy)

6 Roles with Granular Permissions:

RolePermissionsUse Case
OWNERFull access, billing, delete orgOrganization founder
ADMINManage users, clients, campaigns (no billing)Operations manager
MANAGERCreate/edit campaigns, view analyticsCampaign manager
CREATORCreate content, submit for approvalContent creator
VIEWERRead-only access to campaigns and analyticsStakeholders, clients
AUDITORRead-only access to audit logs, complianceCompliance officer

Permission Matrix:

const PERMISSIONS = {
OWNER: ['*'], // All permissions
ADMIN: [
'users.create', 'users.read', 'users.update', 'users.delete',
'clients.create', 'clients.read', 'clients.update', 'clients.delete',
'campaigns.create', 'campaigns.read', 'campaigns.update', 'campaigns.delete',
'analytics.read',
],
MANAGER: [
'clients.read',
'campaigns.create', 'campaigns.read', 'campaigns.update',
'analytics.read',
],
CREATOR: [
'campaigns.create', 'campaigns.read',
],
VIEWER: [
'campaigns.read', 'analytics.read',
],
AUDITOR: [
'audit-logs.read', 'compliance.read',
],
};

Middleware Implementation:

const requirePermission = (permission: string) => {
return async (req, res, next) => {
const userRole = req.auth.role;
const userPermissions = PERMISSIONS[userRole] || [];
if (!userPermissions.includes('*') && !userPermissions.includes(permission)) {
return res.status(403).json({
error: 'Insufficient permissions',
required: permission,
current: userPermissions,
});
}
next();
};
};
// Usage
router.delete(
'/api/clients/:id',
requireAuth,
requirePermission('clients.delete'),
deleteClient
);

MetricTargetCurrentStatus
API Response Time (p50)<200ms147ms✅ EXCEEDS
API Response Time (p95)<500ms312ms✅ EXCEEDS
API Response Time (p99)<1000ms678ms✅ EXCEEDS
Database Query Time<50ms28ms✅ EXCEEDS
Page Load Time (First Contentful Paint)<1.5s1.1s✅ EXCEEDS
Time to Interactive (TTI)<3s2.3s✅ EXCEEDS
Lighthouse Score>9094✅ EXCEEDS

Horizontal Scaling:

  • Stateless API servers (can add infinite instances)
  • Load balancer distributes traffic (Nginx/AWS ALB)
  • Database connection pooling (Prisma manages connections)
  • Redis cache shared across all instances

Vertical Scaling:

  • Database can scale to 96 vCPUs, 768GB RAM (AWS RDS)
  • Redis can scale to 6.1TB memory (AWS ElastiCache)

Load Testing Results:

Scenario: 1,000 concurrent users
- API servers: 3 instances (4 vCPU, 8GB RAM each)
- Database: PostgreSQL 16 (16 vCPU, 64GB RAM)
- Cache: Redis (8GB)
Results:
- Average response time: 189ms
- Error rate: 0.02%
- Throughput: 2,500 requests/second
- Database CPU: 34%
- API CPU: 52%
Conclusion: Can handle 3x current load without additional resources
Cache LayerTechnologyTTLUse Case
CDNCloudflare24 hoursStatic assets (JS, CSS, images)
API ResponseRedis5 minutesFrequently accessed data (clients, campaigns)
Database QueryPrisma1 minuteComputed analytics, dashboards
BrowserService Worker1 hourOffline-first PWA capabilities

Test TypeFrameworkCoverageTest Count
Unit TestsJest96%285 tests
Integration TestsJest + Supertest92%78 tests
End-to-End TestsPlaywright85%22 tests
TOTAL-96%385 tests
E2E Tests (22)
/ \
/ Integration \
/ Tests (78) \
/ \
/ Unit Tests (285) \
/________________________________\

1. POPIA Compliance Tests (124 tests)

  • Audit logging accuracy
  • Consent validation
  • Data residency enforcement
  • Data subject rights (access, correction, deletion)

2. Security Clearance Tests (34 tests)

  • Clearance level enforcement
  • Government client access restrictions
  • Clearance expiry handling

3. Multi-Tenancy Tests (56 tests)

  • Organization isolation
  • Cross-tenant data leakage prevention
  • Role-based access control

4. Campaign Workflow Tests (89 tests)

  • Campaign creation
  • Approval workflows
  • Government vs business workflows
  • Analytics accuracy

5. Performance Tests (82 tests)

  • API response time validation
  • Database query optimization
  • Concurrent user handling
  • Rate limiting enforcement

GitHub Actions Pipeline:

name: CI/CD Pipeline
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- Checkout code
- Setup Node.js 20
- Install dependencies
- Run linting (ESLint)
- Run type checking (TypeScript)
- Run unit tests (Jest)
- Run integration tests
- Run E2E tests (Playwright)
- Upload coverage to Codecov
build:
needs: test
steps:
- Build frontend (Next.js)
- Build backend (TypeScript)
- Run production build validation
deploy:
needs: build
if: github.ref == 'refs/heads/main'
steps:
- Deploy to staging
- Run smoke tests
- Deploy to production (manual approval)

┌─────────────────────────────────────────────────────────────┐
│ CLOUDFLARE CDN │
│ (DDoS protection, SSL) │
└───────────────────────┬─────────────────────────────────────┘
┌───────────────┴────────────────┐
│ │
┌───────▼──────────┐ ┌──────────▼────────┐
│ Frontend (Vercel)│ │ Backend (Railway) │
│ - Next.js App │ │ - Express API │
│ - Edge Functions │ │ - 3 instances │
│ - Auto-scaling │ │ - Load balanced │
└───────────────────┘ └──────────┬────────┘
┌─────────────────┴──────────────────┐
│ │
┌─────────▼─────────┐ ┌──────────▼────────┐
│ PostgreSQL (AWS) │ │ Redis (AWS) │
│ - RDS Multi-AZ │ │ - ElastiCache │
│ - Auto backups │ │ - Cluster mode │
└────────────────────┘ └───────────────────┘

Docker Compose (Local Development):

version: '3.8'
services:
backend:
build: ./backend
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/thrivesend
- REDIS_URL=redis://cache:6379
depends_on:
- db
- cache
frontend:
build: ./frontend
ports:
- "3000:3000"
environment:
- NEXT_PUBLIC_API_URL=http://localhost:8000
db:
image: postgres:16
environment:
- POSTGRES_DB=thrivesend
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
volumes:
- postgres_data:/var/lib/postgresql/data
cache:
image: redis:7
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
EnvironmentPurposeURLDatabaseAuto-Deploy
DevelopmentLocal developmentlocalhost:3000Local PostgreSQLN/A
StagingPre-production testingstaging.thrivesend.co.zaStaging RDSYes (on merge to develop)
ProductionLive customer trafficapp.thrivesend.co.zaProduction RDSManual approval

Integration TypeProvidersStatusPurpose
Email MarketingMailchimp, SendGrid, AWS SES✅ AvailableCampaign distribution
Social MediaFacebook, LinkedIn, Twitter🔄 Q1 2026Multi-channel campaigns
AnalyticsGoogle Analytics, PostHog✅ AvailableCampaign tracking
CRMSalesforce, HubSpot🔄 Q2 2026Client data sync
PaymentStripe✅ AvailableSubscription billing
StorageAWS S3, Cloudflare R2✅ AvailableAsset management
SSOGoogle Workspace, Microsoft AD✅ AvailableEnterprise authentication

ThriveSend can send webhooks for key events:

Available Events:

campaign.created
campaign.published
campaign.completed
client.created
client.updated
analytics.milestone_reached (e.g., 10k impressions)

Webhook Payload Example:

{
"event": "campaign.published",
"timestamp": "2025-11-12T10:30:00Z",
"organizationId": "org_abc123",
"data": {
"campaignId": "camp_xyz789",
"name": "Provincial Health Awareness Campaign",
"clientId": "client_gov456",
"publishedBy": "user_alice",
"channels": ["email", "social"]
}
}

ComponentToolPurpose
Error TrackingSentryReal-time error monitoring, stack traces
Log AggregationBetter Stack (LogTail)Centralized logging, search
Uptime MonitoringUptime Robot99.9% SLA tracking
Performance MonitoringVercel AnalyticsFrontend performance, Web Vitals
Database MonitoringAWS CloudWatchDatabase performance, slow queries
User AnalyticsPostHogFeature adoption, user behavior

Application Metrics:

  • API response times (p50, p95, p99)
  • Error rates (4xx, 5xx)
  • Request throughput (requests/second)
  • Cache hit rates

Business Metrics:

  • Active organizations
  • Active campaigns
  • API usage per tier
  • Conversion rates (free → paid)

Infrastructure Metrics:

  • CPU/memory usage
  • Database connections
  • Redis memory usage
  • Network bandwidth

Critical Alerts (PagerDuty):

  • API error rate >1% (5-minute window)
  • API p95 response time >1s
  • Database CPU >80%
  • Service downtime detected

Warning Alerts (Email):

  • API error rate >0.5%
  • API p95 response time >500ms
  • Database connections >70% capacity
  • Cache hit rate <80%

🔄 Disaster Recovery & Business Continuity

Section titled “🔄 Disaster Recovery & Business Continuity”
Data TypeFrequencyRetentionRecovery Time Objective (RTO)
DatabaseContinuous (AWS RDS)35 days<1 hour
Database (Manual)Daily90 days<4 hours
Files/AssetsReal-time (S3 versioning)Indefinite<15 minutes
Redis CacheHourly snapshots7 days<30 minutes
CodeGit (GitHub)Indefinite<5 minutes

Scenario 1: Database Failure

1. AWS RDS automatically fails over to standby instance (Multi-AZ)
2. Application reconnects automatically (connection pooling)
3. RTO: <5 minutes
4. RPO: 0 (synchronous replication)

Scenario 2: Regional Outage (AWS Cape Town)

1. Failover to AWS eu-west-1 (Ireland) backup region
2. DNS updated to point to backup region (Route 53)
3. Database restored from latest snapshot
4. RTO: 2-4 hours
5. RPO: <1 hour

Scenario 3: Complete Data Loss

1. Restore database from daily backup (S3)
2. Restore files from S3 versioned buckets
3. Rebuild application from Git repository
4. RTO: 6-8 hours
5. RPO: <24 hours
  • Frontend: Multi-region deployment via Vercel edge network
  • Backend: 3 API instances behind load balancer (99.9% uptime)
  • Database: Multi-AZ deployment (automatic failover)
  • Cache: Redis Cluster mode (automatic failover)

Uptime SLA: 99.9% (8.76 hours downtime/year max)


  • ✅ Real-time collaboration (WebSocket support)
  • ✅ Mobile apps (iOS + Android - React Native)
  • ✅ Advanced ML analytics (predictive campaign performance)
  • ✅ Email platform integrations (Mailchimp, SendGrid)
  • ✅ Social media integrations (Facebook, LinkedIn)
  • ✅ CRM integrations (Salesforce, HubSpot)
  • ✅ Multi-language support (Afrikaans, isiZulu, isiXhosa)
  • ✅ Advanced approval workflows (custom chains)
  • ✅ White-label capabilities (custom branding)

For Technical Questions:

For Integration Support:


TermDefinition
B2B2GBusiness-to-Business-to-Government (service providers serving both sectors)
POPIAProtection of Personal Information Act (South African data protection law)
Multi-TenancySingle application instance serving multiple isolated organizations
RBACRole-Based Access Control (permissions based on user roles)
RTORecovery Time Objective (max downtime acceptable)
RPORecovery Point Objective (max data loss acceptable)
  • ✅ POPIA Compliant (self-assessed, third-party audit pending)
  • ✅ ISO 27001 preparation (target Q2 2026)
  • ✅ GDPR compatible (for international clients)

Client Requirements:

  • Modern web browser (Chrome 90+, Firefox 88+, Safari 14+, Edge 90+)
  • JavaScript enabled
  • Internet connection (minimum 1 Mbps)
  • Screen resolution: 1280x720 or higher

API Client Requirements:

  • HTTP/1.1 or HTTP/2 support
  • TLS 1.3 support
  • JSON parsing capabilities

ThriveSend B2B2G represents a production-ready, technically robust marketing platform architected specifically for the South African B2B2G market. Key technical strengths:

Modern Stack: Next.js 15, React 18, TypeScript, PostgreSQL, Prisma ✅ Performance: Sub-200ms API responses, 96% test coverage ✅ Security: POPIA-compliant, government-grade security clearances ✅ Scalability: Proven multi-tenant architecture, horizontal scaling ✅ Reliability: 99.9% uptime SLA, comprehensive disaster recovery

Ready for enterprise deployment.


ThriveSend B2B2G Technical Whitepaper Version 1.0 | 12/11/2025 iSu Technologies (Pty) Ltd