Skip to content

Database Schema - ThriveSend B2B2G

Version: 0.1.4 Last Updated: September 25, 2025 Status: Production ORM: Prisma Database: PostgreSQL 16 Total Models: 28


The ThriveSend B2B2G database schema is designed for multi-tenant B2B2G operations with complete data isolation, POPIA compliance, and government-grade security. The schema uses Prisma ORM with PostgreSQL 16 and implements 28 interconnected models.


erDiagram
Organization ||--o{ OrganizationUser : "has many"
Organization ||--o{ Client : "serves"
Organization ||--o{ Campaign : "creates"
Organization ||--o{ Content : "owns"
Organization ||--o{ Template : "uses"
Organization ||--o{ Project : "manages"
Organization ||--o{ Invitation : "sends"
Organization ||--o{ AuditLog : "generates"
Organization ||--o{ Subscription : "has"
Organization ||--o{ ApiKey : "owns"
Organization ||--o{ Webhook : "configures"
Organization ||--o{ ComplianceConfiguration : "configures"
Organization ||--o{ SecurityConfiguration : "configures"
Client ||--o{ ClientAccess : "grants"
Client ||--o{ Campaign : "receives"
Client ||--o{ Project : "participates"
Client ||--o{ Analytics : "generates"
OrganizationUser ||--o{ ClientAccess : "has access"
OrganizationUser ||--o{ Campaign : "manages"
OrganizationUser ||--o{ Content : "creates"
OrganizationUser ||--o{ ContentApproval : "approves"
OrganizationUser ||--o{ AuditLog : "performs actions"
OrganizationUser ||--o{ Invitation : "receives"
Campaign ||--o{ Content : "contains"
Campaign ||--o{ Analytics : "tracks"
Content ||--o{ ContentVersion : "versioned"
Content ||--o{ ContentApproval : "requires approval"
Content ||--o{ MediaAsset : "includes"
Content ||--o{ EmailTracking : "tracks delivery"
Subscription ||--o{ Invoice : "generates"
Webhook ||--o{ WebhookDelivery : "delivers"
Organization ||--o{ DataProcessingRecord : "maintains"
Organization ||--o{ PopiaConsentRecord : "tracks"
Organization ||--o{ DataSubjectRequest : "handles"
Organization ||--o{ IpWhitelist : "maintains"
Organization ||--o{ NotificationPreferences : "configures"
Invitation ||--o{ InvitationAuditLog : "logs"
Organization {
string id PK "Clerk org ID"
string name
string slug "Unique URL slug"
enum serviceType "B2B, B2G, B2B2G"
jsonb settings
datetime createdAt
datetime updatedAt
}
Client {
string id PK
string organizationId FK
string name
enum sector "GOVERNMENT, BUSINESS"
enum clientType "SME, LARGE_CORP, etc"
enum securityClearance "BASIC, ENHANCED, CONFIDENTIAL"
jsonb contactInfo
datetime createdAt
}
OrganizationUser {
string id PK
string clerkUserId "Clerk user ID"
string organizationId FK
enum role "SERVICE_PROVIDER_ADMIN, etc"
enum securityClearance
jsonb permissions
datetime createdAt
}
ClientAccess {
string id PK
string userId FK
string clientId FK
enum accessLevel "READ, WRITE, ADMIN"
datetime grantedAt
}
Campaign {
string id PK
string organizationId FK
string clientId FK
string name
enum status "DRAFT, ACTIVE, COMPLETED"
enum campaignType
datetime startDate
datetime endDate
jsonb targeting
datetime createdAt
}
Content {
string id PK
string organizationId FK
string campaignId FK
string title
text body
enum status "DRAFT, APPROVED, PUBLISHED"
enum dataClassification "PUBLIC, CONFIDENTIAL"
int version
datetime createdAt
}
ContentVersion {
string id PK
string contentId FK
int versionNumber
text body
string createdBy
datetime createdAt
}
ContentApproval {
string id PK
string contentId FK
string approverId FK
enum status "PENDING, APPROVED, REJECTED"
text comments
datetime approvedAt
}
MediaAsset {
string id PK
string organizationId FK
string contentId FK
string fileName
string fileUrl
string mimeType
int fileSize
enum classification
datetime uploadedAt
}
Analytics {
string id PK
string organizationId FK
string campaignId FK
string clientId FK
jsonb metrics
date reportDate
datetime createdAt
}
Template {
string id PK
string organizationId FK
string name
enum category "EMAIL, SMS, SOCIAL"
text content
jsonb variables
datetime createdAt
}
Project {
string id PK
string organizationId FK
string clientId FK
string name
enum status "ACTIVE, COMPLETED"
date startDate
date endDate
datetime createdAt
}
AuditLog {
string id PK
string organizationId FK
string userId FK
string action
string resource
jsonb details
string ipAddress
datetime timestamp
}
DataProcessingRecord {
string id PK
string organizationId FK
string dataSubject
string processingPurpose
string legalBasis
date retentionDate
datetime createdAt
}
Invitation {
string id PK
string organizationId FK
string email
enum role
string token "Secure invite token"
enum status "PENDING, ACCEPTED, EXPIRED"
datetime expiresAt
datetime createdAt
}
InvitationAuditLog {
string id PK
string invitationId FK
string action
jsonb details
datetime timestamp
}
PopiaConsentRecord {
string id PK
string organizationId FK
string dataSubject
string consentType
boolean consentGiven
datetime consentDate
datetime expiryDate
}
DataSubjectRequest {
string id PK
string organizationId FK
string requester
enum requestType "ACCESS, CORRECTION, DELETION"
enum status "PENDING, COMPLETED"
datetime requestDate
datetime completedDate
}
EmailTracking {
string id PK
string contentId FK
string recipientEmail
enum status "SENT, DELIVERED, OPENED, CLICKED"
datetime sentAt
datetime deliveredAt
}
Subscription {
string id PK
string organizationId FK
enum plan "FREE, PROFESSIONAL, ENTERPRISE"
enum status "ACTIVE, CANCELLED"
date startDate
date endDate
decimal amount
}
Invoice {
string id PK
string subscriptionId FK
string invoiceNumber
decimal amount
enum status "PAID, PENDING, OVERDUE"
date issueDate
date dueDate
}
ApiKey {
string id PK
string organizationId FK
string key "Encrypted API key"
string name
jsonb permissions
datetime expiresAt
datetime createdAt
}
Webhook {
string id PK
string organizationId FK
string url
string[] events
string secret
boolean active
datetime createdAt
}
WebhookDelivery {
string id PK
string webhookId FK
string event
jsonb payload
int statusCode
datetime attemptedAt
}
IpWhitelist {
string id PK
string organizationId FK
string ipAddress
string description
boolean active
datetime createdAt
}
NotificationPreferences {
string id PK
string organizationId FK
string userId
jsonb preferences
datetime updatedAt
}
ComplianceConfiguration {
string id PK
string organizationId FK
boolean popiaEnabled
string dataResidency "ZA"
int retentionPeriodDays
jsonb settings
datetime updatedAt
}
SecurityConfiguration {
string id PK
string organizationId FK
boolean mfaRequired
boolean ipWhitelistEnabled
int sessionTimeoutMinutes
jsonb settings
datetime updatedAt
}

Purpose: Multi-tenant service provider organizations

FieldTypeDescription
idString (PK)Clerk organization ID
nameStringOrganization name
slugString (Unique)URL-friendly identifier
serviceTypeEnumB2B, B2G, or B2B2G
settingsJSONOrganization configuration
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relationships:

  • Has many: OrganizationUsers, Clients, Campaigns, Content, Templates, Projects
  • Has many: Invitations, AuditLogs, Subscriptions, ApiKeys, Webhooks
  • Has one: ComplianceConfiguration, SecurityConfiguration

Purpose: B2B2G clients (government and business)

FieldTypeDescription
idString (PK)Unique client ID
organizationIdString (FK)Parent organization
nameStringClient name
sectorEnumGOVERNMENT or BUSINESS
clientTypeEnumSME, LARGE_CORP, GOVERNMENT_NATIONAL, etc.
securityClearanceEnumBASIC, ENHANCED, CONFIDENTIAL
contactInfoJSONContact details
createdAtDateTimeCreation timestamp

Relationships:

  • Belongs to: Organization
  • Has many: ClientAccess, Campaigns, Projects, Analytics

Purpose: Users within service provider organizations

FieldTypeDescription
idString (PK)Unique user ID
clerkUserIdStringClerk authentication ID
organizationIdString (FK)Parent organization
roleEnumSERVICE_PROVIDER_ADMIN, ACCOUNT_MANAGER, etc.
securityClearanceEnumBASIC, ENHANCED, CONFIDENTIAL
permissionsJSONRole-based permissions
createdAtDateTimeCreation timestamp

Relationships:

  • Belongs to: Organization
  • Has many: ClientAccess, Campaigns, Content, ContentApprovals, AuditLogs

Purpose: User access control per client

FieldTypeDescription
idString (PK)Unique access ID
userIdString (FK)Organization user
clientIdString (FK)Target client
accessLevelEnumREAD, WRITE, ADMIN
grantedAtDateTimeAccess grant timestamp

Relationships:

  • Belongs to: OrganizationUser, Client

Purpose: Marketing campaigns with sector-specific compliance

FieldTypeDescription
idString (PK)Unique campaign ID
organizationIdString (FK)Owner organization
clientIdString (FK)Target client
nameStringCampaign name
statusEnumDRAFT, ACTIVE, COMPLETED, CANCELLED
campaignTypeEnumEMAIL, SMS, SOCIAL, MULTI_CHANNEL
startDateDateTimeCampaign start
endDateDateTimeCampaign end
targetingJSONTargeting criteria
createdAtDateTimeCreation timestamp

Relationships:

  • Belongs to: Organization, Client, OrganizationUser (manager)
  • Has many: Content, Analytics

Purpose: Content entities with government approval workflows

FieldTypeDescription
idString (PK)Unique content ID
organizationIdString (FK)Owner organization
campaignIdString (FK)Parent campaign
titleStringContent title
bodyTextContent body
statusEnumDRAFT, PENDING_APPROVAL, APPROVED, PUBLISHED
dataClassificationEnumPUBLIC, COMMERCIAL, CONFIDENTIAL, RESTRICTED
versionIntCurrent version number
createdAtDateTimeCreation timestamp

Relationships:

  • Belongs to: Organization, Campaign, OrganizationUser (creator)
  • Has many: ContentVersions, ContentApprovals, MediaAssets, EmailTracking

Purpose: Version control for content

FieldTypeDescription
idString (PK)Unique version ID
contentIdString (FK)Parent content
versionNumberIntSequential version
bodyTextVersion content
createdByStringUser ID
createdAtDateTimeVersion timestamp

Relationships:

  • Belongs to: Content

Purpose: Approval workflow tracking

FieldTypeDescription
idString (PK)Unique approval ID
contentIdString (FK)Target content
approverIdString (FK)Approving user
statusEnumPENDING, APPROVED, REJECTED
commentsTextApproval comments
approvedAtDateTimeApproval timestamp

Relationships:

  • Belongs to: Content, OrganizationUser (approver)

Purpose: Media file management with POPIA classification

FieldTypeDescription
idString (PK)Unique asset ID
organizationIdString (FK)Owner organization
contentIdString (FK)Associated content (optional)
fileNameStringOriginal filename
fileUrlStringStorage URL
mimeTypeStringFile MIME type
fileSizeIntSize in bytes
classificationEnumPUBLIC, CONFIDENTIAL, RESTRICTED
uploadedAtDateTimeUpload timestamp

Relationships:

  • Belongs to: Organization, Content (optional)

Purpose: Performance metrics and reporting

FieldTypeDescription
idString (PK)Unique analytics ID
organizationIdString (FK)Owner organization
campaignIdString (FK)Target campaign (optional)
clientIdString (FK)Target client (optional)
metricsJSONPerformance data
reportDateDateReport date
createdAtDateTimeCreation timestamp

Relationships:

  • Belongs to: Organization, Campaign (optional), Client (optional)

Purpose: Content templates with sector-specific options

FieldTypeDescription
idString (PK)Unique template ID
organizationIdString (FK)Owner organization
nameStringTemplate name
categoryEnumEMAIL, SMS, SOCIAL, DOCUMENT
contentTextTemplate content
variablesJSONVariable definitions
createdAtDateTimeCreation timestamp

Relationships:

  • Belongs to: Organization

Purpose: Project management for clients

FieldTypeDescription
idString (PK)Unique project ID
organizationIdString (FK)Owner organization
clientIdString (FK)Target client
nameStringProject name
statusEnumACTIVE, COMPLETED, ON_HOLD
startDateDateProject start
endDateDateProject end
createdAtDateTimeCreation timestamp

Relationships:

  • Belongs to: Organization, Client

Purpose: Comprehensive audit trails for POPIA compliance

FieldTypeDescription
idString (PK)Unique log ID
organizationIdString (FK)Owner organization
userIdString (FK)Acting user
actionStringAction performed
resourceStringAffected resource
detailsJSONAction details
ipAddressStringUser IP address
timestampDateTimeAction timestamp

Relationships:

  • Belongs to: Organization, OrganizationUser

Purpose: Data processing records for POPIA

FieldTypeDescription
idString (PK)Unique record ID
organizationIdString (FK)Owner organization
dataSubjectStringData subject identifier
processingPurposeStringPurpose of processing
legalBasisStringLegal basis (consent, contract, etc.)
retentionDateDateData retention until
createdAtDateTimeRecord creation

Relationships:

  • Belongs to: Organization

Purpose: Custom POPIA-compliant invitation system

FieldTypeDescription
idString (PK)Unique invitation ID
organizationIdString (FK)Inviting organization
emailStringInvitee email
roleEnumInvited role
tokenStringSecure invite token
statusEnumPENDING, ACCEPTED, EXPIRED, CANCELLED
expiresAtDateTimeExpiration timestamp
createdAtDateTimeCreation timestamp

Relationships:

  • Belongs to: Organization
  • Has many: InvitationAuditLogs

Purpose: Invitation audit trail

FieldTypeDescription
idString (PK)Unique log ID
invitationIdString (FK)Parent invitation
actionStringAction performed
detailsJSONAction details
timestampDateTimeAction timestamp

Relationships:

  • Belongs to: Invitation

Purpose: Consent tracking and management

FieldTypeDescription
idString (PK)Unique consent ID
organizationIdString (FK)Owner organization
dataSubjectStringData subject identifier
consentTypeStringType of consent
consentGivenBooleanConsent status
consentDateDateTimeConsent timestamp
expiryDateDateTimeConsent expiry (optional)

Relationships:

  • Belongs to: Organization

Purpose: Data subject rights handling

FieldTypeDescription
idString (PK)Unique request ID
organizationIdString (FK)Owner organization
requesterStringRequester identifier
requestTypeEnumACCESS, CORRECTION, DELETION, PORTABILITY
statusEnumPENDING, IN_PROGRESS, COMPLETED, REJECTED
requestDateDateTimeRequest timestamp
completedDateDateTimeCompletion timestamp (optional)

Relationships:

  • Belongs to: Organization

Purpose: Email delivery tracking

FieldTypeDescription
idString (PK)Unique tracking ID
contentIdString (FK)Associated content
recipientEmailStringRecipient address
statusEnumSENT, DELIVERED, OPENED, CLICKED, BOUNCED
sentAtDateTimeSend timestamp
deliveredAtDateTimeDelivery timestamp (optional)

Relationships:

  • Belongs to: Content

Purpose: Subscription management

FieldTypeDescription
idString (PK)Unique subscription ID
organizationIdString (FK)Owner organization
planEnumFREE, PROFESSIONAL, ENTERPRISE
statusEnumACTIVE, CANCELLED, EXPIRED
startDateDateSubscription start
endDateDateSubscription end
amountDecimalMonthly amount

Relationships:

  • Belongs to: Organization
  • Has many: Invoices

Purpose: Invoice history

FieldTypeDescription
idString (PK)Unique invoice ID
subscriptionIdString (FK)Parent subscription
invoiceNumberStringInvoice reference
amountDecimalInvoice amount
statusEnumPAID, PENDING, OVERDUE, CANCELLED
issueDateDateIssue date
dueDateDateDue date

Relationships:

  • Belongs to: Subscription

Purpose: API key management

FieldTypeDescription
idString (PK)Unique key ID
organizationIdString (FK)Owner organization
keyStringEncrypted API key
nameStringKey name/description
permissionsJSONKey permissions
expiresAtDateTimeExpiration timestamp (optional)
createdAtDateTimeCreation timestamp

Relationships:

  • Belongs to: Organization

Purpose: Webhook configuration

FieldTypeDescription
idString (PK)Unique webhook ID
organizationIdString (FK)Owner organization
urlStringWebhook endpoint URL
eventsString[]Subscribed events
secretStringWebhook signing secret
activeBooleanActive status
createdAtDateTimeCreation timestamp

Relationships:

  • Belongs to: Organization
  • Has many: WebhookDeliveries

Purpose: Webhook delivery logs

FieldTypeDescription
idString (PK)Unique delivery ID
webhookIdString (FK)Parent webhook
eventStringEvent type
payloadJSONEvent payload
statusCodeIntHTTP status code
attemptedAtDateTimeAttempt timestamp

Relationships:

  • Belongs to: Webhook

Purpose: IP whitelist management

FieldTypeDescription
idString (PK)Unique whitelist ID
organizationIdString (FK)Owner organization
ipAddressStringWhitelisted IP
descriptionStringDescription
activeBooleanActive status
createdAtDateTimeCreation timestamp

Relationships:

  • Belongs to: Organization

Purpose: Notification settings

FieldTypeDescription
idString (PK)Unique preference ID
organizationIdString (FK)Owner organization
userIdStringUser ID (optional)
preferencesJSONNotification settings
updatedAtDateTimeLast update

Relationships:

  • Belongs to: Organization

Purpose: POPIA compliance settings

FieldTypeDescription
idString (PK)Unique config ID
organizationIdString (FK)Owner organization
popiaEnabledBooleanPOPIA compliance enabled
dataResidencyStringData residency (default: “ZA”)
retentionPeriodDaysIntData retention period
settingsJSONCompliance settings
updatedAtDateTimeLast update

Relationships:

  • Belongs to: Organization

Purpose: Security settings

FieldTypeDescription
idString (PK)Unique config ID
organizationIdString (FK)Owner organization
mfaRequiredBooleanMFA requirement
ipWhitelistEnabledBooleanIP whitelist enabled
sessionTimeoutMinutesIntSession timeout
settingsJSONSecurity settings
updatedAtDateTimeLast update

Relationships:

  • Belongs to: Organization

-- Organization lookups
CREATE INDEX idx_organization_slug ON Organization(slug);
-- User lookups
CREATE INDEX idx_organization_user_clerk_id ON OrganizationUser(clerkUserId);
CREATE INDEX idx_organization_user_org_id ON OrganizationUser(organizationId);
-- Client lookups
CREATE INDEX idx_client_org_id ON Client(organizationId);
CREATE INDEX idx_client_sector ON Client(sector);
-- Campaign lookups
CREATE INDEX idx_campaign_org_id ON Campaign(organizationId);
CREATE INDEX idx_campaign_client_id ON Campaign(clientId);
CREATE INDEX idx_campaign_status ON Campaign(status);
-- Content lookups
CREATE INDEX idx_content_campaign_id ON Content(campaignId);
CREATE INDEX idx_content_status ON Content(status);
-- Audit log queries
CREATE INDEX idx_audit_log_org_id ON AuditLog(organizationId);
CREATE INDEX idx_audit_log_user_id ON AuditLog(userId);
CREATE INDEX idx_audit_log_timestamp ON AuditLog(timestamp);
-- Invitation lookups
CREATE INDEX idx_invitation_email ON Invitation(email);
CREATE INDEX idx_invitation_token ON Invitation(token);
CREATE INDEX idx_invitation_status ON Invitation(status);

  • Encryption at Rest: All sensitive fields encrypted
  • Data Residency: South African data center requirement
  • Audit Trail: Complete audit logging for all operations
  • Consent Management: PopiaConsentRecord tracking
  • Data Subject Rights: DataSubjectRequest handling
  • Audit Logs: 5+ years retention
  • Client Data: Configurable per organization
  • Campaign Data: 3 years default
  • Consent Records: Indefinite retention

  1. Development: Test migrations in dev environment
  2. Staging: Validate migrations with production-like data
  3. Production: Apply migrations during maintenance window
  4. Rollback: Maintain rollback scripts for critical changes
  • v0.1.0: Initial 28-model schema
  • v0.1.1: Added invitation audit logging
  • v0.1.2: Enhanced security clearance fields
  • v0.1.3: Added email tracking
  • v0.1.4: Production optimization indexes

  • Organization lookups: <10ms (indexed slug)
  • User authentication: <15ms (indexed Clerk ID)
  • Campaign queries: <50ms (indexed org + client)
  • Audit log queries: <100ms (indexed timestamp)
  • Multi-tenant isolation: Complete data separation
  • Read replicas: Supported for analytics queries
  • Connection pooling: Prisma connection management
  • Caching layer: Redis for frequently accessed data


Last Updated: September 25, 2025 Verified: Production v0.1.4