16 KiB
Architecture Documentation
Service: mkt-whatsapp-service-net
Version: 1.0
Last Updated: 2026-01-18
System Overview
The MKT WhatsApp Service is a comprehensive microservice built on Clean Architecture principles, implementing Domain-Driven Design (DDD) and CQRS patterns. It provides three core capabilities:
- Automation Chatbot: Rule-based conversation flows
- AI Chatbot: LLM-powered intelligent responses
- Customer Management: Unified CRM for WhatsApp interactions
High-Level Architecture
graph TB
subgraph External
WA[WhatsApp Cloud API]
OPENAI[OpenAI GPT-4]
Customer[End Users]
end
subgraph "GoodGo Platform"
GATEWAY[Traefik Gateway]
subgraph "mkt-whatsapp-service-net"
API[API Layer]
APP[Application Layer]
DOMAIN[Domain Layer]
INFRA[Infrastructure Layer]
end
PG[(PostgreSQL)]
REDIS[(Redis)]
RABBIT[RabbitMQ]
end
subgraph "Other Services"
MERCHANT[merchant-service]
ANALYTICS[analytics-service]
end
Customer -->|Messages| WA
WA -->|Webhooks| GATEWAY
GATEWAY --> API
API --> APP
APP --> DOMAIN
APP --> INFRA
INFRA --> PG
INFRA --> REDIS
INFRA --> WA
INFRA --> OPENAI
INFRA --> RABBIT
RABBIT --> MERCHANT
RABBIT --> ANALYTICS
style Customer fill:#2C3E50,color:#ECF0F1,stroke:#34495E,stroke-width:3px
style WA fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:3px
style OPENAI fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:3px
style GATEWAY fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:3px
style API fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
style APP fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
style DOMAIN fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
style INFRA fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
style PG fill:#34495E,color:#ECF0F1,stroke:#2C3E50,stroke-width:2px
style REDIS fill:#34495E,color:#ECF0F1,stroke:#2C3E50,stroke-width:2px
style RABBIT fill:#34495E,color:#ECF0F1,stroke:#2C3E50,stroke-width:2px
style MERCHANT fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
style ANALYTICS fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
Clean Architecture Layers
1. API Layer (MktWhatsAppService.API)
Responsibility: HTTP interface, request/response handling
Controllers
WebhooksController- WhatsApp webhook verification and message eventsWhatsAppAccountsController- Account connection managementConversationsController- Conversation and message endpointsCustomersController- Customer profile managementAutomationFlowsController- Automation flow CRUDAIAgentsController- AI agent configurationAnalyticsController- Metrics and reporting
Background Jobs
ConversationExpiryJob- Close expired 24h conversationsMessageStatusSyncJob- Sync delivery/read status from WhatsAppFlowSchedulerJob- Trigger time-based automation flows
2. Application Layer (MktWhatsAppService.API/Application)
Responsibility: Use cases, orchestration, CQRS
Commands (Writes)
WhatsApp Account
ConnectWhatsAppAccountCommand- Register new accountUpdateWebhookCommand- Update webhook configurationDisconnectWhatsAppAccountCommand- Deactivate account
Messages
ProcessIncomingMessageCommand- Handle incoming WhatsApp messageSendMessageCommand- Send outbound messageSendTemplateMessageCommand- Send pre-approved template
Automation
CreateAutomationFlowCommand- Define new flowUpdateFlowStepCommand- Modify flow logicActivateFlowCommand- Enable automationDeactivateFlowCommand- Disable automation
AI Agent
CreateAIAgentCommand- Configure AI chatbotUpdateAgentPersonalityCommand- Modify AI behaviorGenerateAIResponseCommand- Get AI reply
Customers
CreateCustomerCommand- Register new customerUpdateCustomerOptInCommand- Manage opt-in consentTagCustomerCommand- Add/remove tags
Queries (Reads)
Conversations
GetConversationQuery- Single conversation with messagesGetActiveConversationsQuery- List ongoing conversationsSearchConversationsQuery- Full-text search
Customers
GetCustomerQuery- Customer profile by WaIdGetCustomersQuery- Paginated customer listGetCustomerConversationHistoryQuery- All past conversations
Analytics
GetMessageStatsQuery- Message volume metricsGetConversationMetricsQuery- Response times, resolution ratesGetAutomationPerformanceQuery- Flow execution stats
MediatR Pipeline Behaviors
- Logging Behavior - Log all commands/queries
- Validation Behavior - FluentValidation integration
- Transaction Behavior - Unit of Work for commands
3. Domain Layer (MktWhatsAppService.Domain)
Responsibility: Business logic, entities, business rules
Aggregates
WhatsAppAccount Aggregate
Aggregate Root: WhatsAppAccount
Properties:
Id(Guid)ShopId(Guid)PhoneNumberId(string) - WhatsApp phone number IDAccessToken(string, encrypted)WebhookUrl(string)Status(Active/Suspended)MessageTier(1K/10K/100K/Unlimited)
Business Methods:
Activate()- Activate accountUpdateWebhook(url)- Change webhook URLSuspend()- Suspend account
Domain Events:
WhatsAppAccountConnectedEventWebhookVerifiedEvent
Conversation Aggregate
Aggregate Root: Conversation
Properties:
Id(Guid)ShopId(Guid)CustomerWaId(string)Status(Active/Closed/Expired)AssignedAgentId(Guid, nullable)LastMessageAt(DateTime)Tags(List)
Entities:
MessageId(Guid)WhatsAppMessageId(string)Direction(Inbound/Outbound)Content(MessageContent value object)Status(Sent/Delivered/Read/Failed)Timestamp(DateTime)
Business Methods:
AddMessage(content, direction)- Add message to conversationAssignToAgent(agentId)- Assign conversationClose()- Close conversationCheckExpiry()- Check 24h window
Domain Events:
ConversationStartedEventMessageReceivedEventMessageSentEventConversationClosedEvent
AutomationFlow Aggregate
Aggregate Root: AutomationFlow
Properties:
Id(Guid)ShopId(Guid)FlowName(string)TriggerType(Keyword/Event/Schedule)TriggerConfig(JSON)IsActive(bool)
Entities:
FlowStepOrder(int)Action(SendMessage/TagCustomer/CallWebhook/Delay)ActionConfig(JSON)Conditions(JSON, optional)NextStepId(int, nullable)
Business Methods:
AddStep(action, config, conditions)- Add flow stepValidateFlow()- Check for cycles, validate structureActivate()- Enable flowDeactivate()- Disable flow
AIAgent Aggregate
Aggregate Root: AIAgent
Properties:
Id(Guid)ShopId(Guid)AgentName(string)Personality(AgentPersonality value object)KnowledgeBaseId(Guid, nullable)IsActive(bool)
Value Objects:
AgentPersonalityTone(Friendly/Professional/Casual)Language(Vietnamese/English)Constraints(List)PromptTemplate(string)
Business Methods:
UpdatePersonality(personality)- Change AI behaviorActivate()- Enable AI responsesDeactivate()- Disable AI
Customer Aggregate
Aggregate Root: Customer
Properties:
Id(Guid)WaId(string) - WhatsApp ID (phone number)ShopId(Guid)Name(string)ProfilePictureUrl(string, nullable)Consent(OptInConsent value object)Tags(List)CustomFields(Dictionary<string, string>)FirstContactedAt(DateTime)
Value Objects:
OptInConsentStatus(OptedIn/OptedOut/Pending)Timestamp(DateTime)Source(Web/WhatsApp/Manual)
Business Methods:
UpdateOptIn(status, source)- Manage consentAddTag(tag)- Add customer tagRemoveTag(tag)- Remove tagUpdateCustomField(key, value)- Set custom field
4. Infrastructure Layer (MktWhatsAppService.Infrastructure)
Responsibility: External concerns, persistence, API clients
Data Access
MktWhatsAppServiceContext- EF Core DbContext- Entity Configurations using Fluent API
- Repositories implementing domain interfaces
External Services
WhatsAppCloudApiClient
HTTP client for WhatsApp Cloud API with Polly resilience policies:
Methods:
SendMessageAsync()- Send text/media/interactive messagesSendTemplateMessageAsync()- Send pre-approved templatesMarkMessageAsReadAsync()- Send read receiptsGetMediaAsync()- Download media files
Resilience:
- Retry: 3 attempts, exponential backoff (500ms, 1.5s, 4.5s)
- Circuit Breaker: 50% failure ratio, 30s sampling, 30s break
- Timeout: 10s per request
LlmService
LLM provider abstraction (OpenAI implementation):
Methods:
GenerateResponseAsync()- Get AI response with contextExtractIntentAsync()- Classify user intentStreamResponseAsync()- Streaming for long responses
Features:
- Token usage tracking
- Cost calculation
- Context window management (last 10 messages)
- Safety filters
Message Processing Flow
Incoming Message Flow
sequenceDiagram
participant WA as WhatsApp
participant Webhook as WebhooksController
participant Cmd as ProcessIncomingMessageHandler
participant AutoEngine as AutomationEngine
participant AIEngine as AIEngine
participant DB as Database
WA->>Webhook: POST /webhooks (message event)
Webhook->>Webhook: Verify signature
Webhook->>Cmd: ProcessIncomingMessageCommand
Webhook-->>WA: 200 OK (immediate)
Cmd->>DB: Get/Create Conversation
Cmd->>DB: Save Message
alt Active Automation Flow
Cmd->>AutoEngine: Check triggers
AutoEngine->>AutoEngine: Match keywords/conditions
AutoEngine->>WA: Send automated response
else AI Agent Active
Cmd->>AIEngine: GenerateAIResponseCommand
AIEngine->>DB: Get history (last 10 msgs)
AIEngine->>AIEngine: Build prompt
AIEngine->>OpenAI: Chat completion
OpenAI-->>AIEngine: AI response
AIEngine->>WA: Send AI message
else Manual Response
Cmd->>DB: Mark conversation pending
Cmd->>RabbitMQ: Publish event
end
Outbound Message Flow
sequenceDiagram
participant API as ConversationsController
participant Cmd as SendMessageHandler
participant Domain as Conversation Aggregate
participant WA as WhatsAppCloudApiClient
participant DB as Database
API->>Cmd: SendMessageCommand
Cmd->>DB: Get Conversation
Cmd->>Domain: CheckExpiry()
alt Within 24h Window
Domain-->>Cmd: Window valid
Cmd->>WA: SendMessageAsync()
WA-->>Cmd: WhatsApp message ID
Cmd->>Domain: AddMessage()
Cmd->>DB: Save
else Outside 24h Window
Domain-->>Cmd: Window expired
Cmd->>WA: SendTemplateMessageAsync()
WA-->>Cmd: Message ID (new window)
Cmd->>Domain: AddMessage()
Cmd->>DB: Save
end
Data Model
Database Schema
See Database Schema Documentation for detailed table structures and indexes.
Key tables:
whatsapp_accounts- Business account connectionsconversations- Customer conversationsmessages- Individual messages (owned by conversation)customers- Customer profilesautomation_flows- Automation flow definitionsflow_steps- Flow step configurationsai_agents- AI agent configurations
Important Indexes
-- High-traffic queries
CREATE INDEX idx_conversations_shop_status ON conversations(shop_id, status);
CREATE INDEX idx_messages_conversation_timestamp ON messages(conversation_id, timestamp DESC);
CREATE INDEX idx_customers_shop_waid ON customers(shop_id, wa_id);
-- Automation lookups
CREATE INDEX idx_flows_shop_active ON automation_flows(shop_id, is_active);
Integration Events
The service publishes events to RabbitMQ for consumption by other services:
Published Events
WhatsAppMessageReceivedEvent
- Emitted when: Customer sends message to shop
- Consumers: analytics-service (metrics), merchant-service (notifications)
ConversationClosedEvent
- Emitted when: Conversation is closed or expires
- Consumers: analytics-service (conversation duration), merchant-service
AITokenUsageEvent
- Emitted when: AI agent generates response
- Consumers: wallet-service (billing), analytics-service (cost tracking)
CustomerOptInChangedEvent
- Emitted when: Customer opt-in status changes
- Consumers: marketing services (permission updates)
Security Considerations
Webhook Signature Verification
All incoming webhooks from WhatsApp are verified using HMAC-SHA256:
var signature = Request.Headers["X-Hub-Signature-256"];
var payload = await ReadBodyAsStringAsync();
var computedSignature = ComputeHmacSha256(payload, _appSecret);
if (!SecureCompare(signature, computedSignature))
return Unauthorized();
Access Token Encryption
WhatsApp access tokens are encrypted at rest using AES-256-GCM:
// Stored in database as encrypted bytes
public string AccessToken
{
get => _encryption.Decrypt(_encryptedToken);
private set => _encryptedToken = _encryption.Encrypt(value);
}
Rate Limiting
Redis-based distributed rate limiter:
- 60 requests/minute per shop
- 1000 requests/minute per service instance
GDPR Compliance
- Customer data can be exported via API
- Right to be forgotten: soft delete with data anonymization
- Opt-in consent tracking with timestamps
- Data retention policies enforced
Performance Optimization
Caching Strategy
Redis Cache Usage:
- Conversation Context - Last 10 messages (TTL: 1 hour)
- Customer Profiles - Frequently accessed customers (TTL: 30 minutes)
- Active Flows - Automation flows (TTL: 5 minutes)
- Rate Limit Counters - Per-shop request counts (TTL: 1 minute)
Query Optimization
- Use Dapper for read-heavy queries (bypass EF Core)
- Implement pagination for all list endpoints
- Index on foreign keys and commonly filtered columns
- No N+1 queries (use
Include()or projections)
Background Processing
- Webhook processing returns 200 immediately
- Message sending queued to background job
- Flow execution runs asynchronously
Monitoring & Observability
Health Checks
builder.Services.AddHealthChecks()
.AddNpgSql(connectionString, name: "postgres")
.AddRedis(redisConnection, name: "redis")
.AddRabbitMQ(rabbitConnection, name: "rabbitmq")
.AddCheck<WhatsAppApiHealthCheck>("whatsapp-api")
.AddCheck<OpenAIHealthCheck>("openai-api");
Metrics (Prometheus)
whatsapp_messages_received_total- Counterwhatsapp_messages_sent_total- Counterwhatsapp_conversation_duration_seconds- Histogramwhatsapp_ai_tokens_used_total- Counterwhatsapp_webhook_processing_duration_ms- Histogram
Logging (Loki)
Structured logging with Serilog:
- Request/response correlation IDs
- Enriched with
ShopId,ConversationId - Sensitive data (tokens, messages) redacted
Deployment Architecture
See Deployment Guide for Kubernetes manifests and scaling strategies.
Scaling Triggers:
- CPU > 70% → Scale up pods
- Webhook queue > 1000 messages → Scale up
- Memory > 80% → Investigate + scale
Resource Limits:
- Requests: 256Mi memory, 250m CPU
- Limits: 512Mi memory, 500m CPU