Skip to main content

Technical Specification

This document covers the technical details of the CRM & Marketing Platform including event integration, API design, security, and performance requirements.


Event Integration

Event Transport

Phase 1: Redis + BullMQ (existing infrastructure)

Events Consumed

SourceEventCRM Action
SCLmember.createdCreate/link profile, activity
SCLmember.updatedUpdate profile, activity
SCLtier.changedUpdate tier, activity, rescore
SCLpayment.receivedUpdate LTV, activity
TeeTimeplayer.createdCreate/link profile, activity
TeeTimeteetime.bookedActivity, update frequency
TeeTimeteetime.completedActivity, trigger review
TeeTimecompetition.publishedAuto-promote (if enabled)
TeeTimehandicap.updatedActivity, update handicap
Messagingmessage.sentActivity
Messagingmessage.deliveredActivity
Messagingemail.openedActivity, engagement
Messagingemail.clickedActivity, engagement
MessagingcontactPreference.updatedUpdate opt-in flags

Events Produced

EventTriggerConsumers
crm.profile.createdNew profileAnalytics
crm.profile.mergedDuplicate mergeMessaging (update contact)
crm.segment.membership.changedSegment refreshMessaging (sync)
crm.campaign.scheduledCampaign createdJob scheduler
crm.campaign.sentCampaign executedAnalytics
crm.churn.risk.highRisk score > 80Alerting

API Design

REST Endpoints Summary

# Customer Profiles
GET /api/v1/customers
GET /api/v1/customers/:id
GET /api/v1/customers/resolve
POST /api/v1/customers
PATCH /api/v1/customers/:id
POST /api/v1/customers/:id/merge

# Activity Timeline
GET /api/v1/customers/:id/activities
POST /api/v1/customers/:id/activities

# Notes
GET /api/v1/customers/:id/notes
POST /api/v1/customers/:id/notes

# Segments
GET /api/v1/segments
POST /api/v1/segments
GET /api/v1/segments/:id/members
POST /api/v1/segments/:id/refresh
POST /api/v1/segments/:id/sync-to-messaging

# Campaigns
GET /api/v1/campaigns
POST /api/v1/campaigns
GET /api/v1/campaigns/:id
PATCH /api/v1/campaigns/:id
POST /api/v1/campaigns/:id/schedule
POST /api/v1/campaigns/:id/pause
POST /api/v1/campaigns/:id/resume

# Journeys
GET /api/v1/journeys
POST /api/v1/journeys
GET /api/v1/journeys/:id/steps
POST /api/v1/journeys/:id/activate

# Social
GET /api/v1/social/connections
POST /api/v1/social/connections/connect
DELETE /api/v1/social/connections/:id
GET /api/v1/social/posts
POST /api/v1/social/posts
POST /api/v1/social/posts/:id/publish

# Event Promotion
GET /api/v1/promotions
POST /api/v1/promotions
PATCH /api/v1/promotions/:id

# Analytics
GET /api/v1/analytics/engagement
GET /api/v1/analytics/campaigns
GET /api/v1/analytics/social

See API Reference for complete documentation.


Security & Privacy

Multi-Tenancy

  • All queries filtered by tenantId
  • Row-level security enforced
  • No cross-tenant data leakage

Authentication & Authorization

API authenticated via existing IDP tokens.

Role-based access:

RolePermissions
crm:readView profiles, timeline
crm:writeAdd notes, tags
crm:campaignsManage campaigns
crm:socialManage social connections
crm:adminMerge profiles, manage segments

Social Token Security

  • OAuth tokens encrypted at rest (AES-256)
  • Refresh tokens stored separately
  • Token expiry monitored and auto-refreshed
  • Tokens never exposed in API responses

Data Privacy

  • Consent flags synced from Messaging (read-only)
  • GDPR right-to-erasure supported
  • PII encrypted at rest
  • Audit log for all data access

Right to Erasure (GDPR)

async eraseCustomer(profileId: string): Promise<void> {
// 1. Mark profile as DELETED
// 2. Anonymize PII fields
// 3. Remove from all segments
// 4. Notify downstream services
// 5. Create audit log entry
}

Performance Requirements

MetricTarget
Profile lookupunder 100ms p99
Timeline queryunder 500ms p99
Segment refreshunder 30 seconds for 10k members
Campaign schedulingunder 5 seconds
Social post publishunder 10 seconds
Event processingunder 5 seconds

Caching Strategy

DataCache TTLInvalidation
Profile5 minutesOn update
Segment membership1 hourOn refresh
OAuth tokensUntil expiryOn refresh

Database Optimization

Indexes

Primary query patterns are indexed:

-- Customer lookups
CREATE INDEX idx_customer_tenant_email ON CustomerProfile(tenantId, email);
CREATE INDEX idx_customer_tenant_phone ON CustomerProfile(tenantId, phoneNumber);
CREATE INDEX idx_customer_tenant_status ON CustomerProfile(tenantId, status);

-- Timeline queries
CREATE INDEX idx_activity_customer_date ON Activity(customerId, occurredAt DESC);

-- Segment queries
CREATE INDEX idx_membership_segment ON CustomerSegmentMembership(segmentId, customerId);

Partitioning (Future)

For high-volume tables:

-- Activity table partitioned by month
CREATE TABLE Activity (
...
) PARTITION BY RANGE (occurredAt);

Scaling Considerations

Current Design (v1)

  • Single CRM database
  • Redis/BullMQ for events
  • 2 API replicas

Future Scale (v2)

ComponentScale Strategy
DatabaseRead replicas, connection pooling
Event processingKafka for higher throughput
SearchElasticsearch for full-text
CacheRedis Cluster
APIHorizontal scaling

Estimated Capacity (v1)

MetricCapacity
Profiles1M+
Activities/day100K+
Campaigns/day1000+
Events/second100+

Monitoring & Observability

Metrics

MetricTypeDescription
crm_profiles_totalGaugeTotal profiles
crm_events_processed_totalCounterEvents processed
crm_event_processing_durationHistogramProcessing time
crm_api_request_durationHistogramAPI latency
crm_campaign_sent_totalCounterMessages sent

Alerts

AlertConditionSeverity
High event queue depthQueue > 10,000Warning
Event processing failuresRate > 5%Critical
API latency spikep99 > 1sWarning
Database connection pool exhaustedAvailable < 10%Critical

Logging

Structured JSON logs with:

{
"timestamp": "2024-12-14T10:00:00Z",
"level": "info",
"service": "crm",
"traceId": "abc123",
"event": "profile.created",
"tenantId": "tenant_123",
"profileId": "profile_456"
}

Error Handling

Retry Strategy

const retryConfig = {
attempts: 3,
backoff: {
type: 'exponential',
delay: 1000, // 1s, 2s, 4s
},
};

Dead Letter Queue

Failed events after all retries go to DLQ:

const dlqConfig = {
name: 'crm-events-dlq',
retentionDays: 7,
};

Circuit Breaker

For external service calls (Messaging, Social):

const circuitBreaker = {
threshold: 5, // failures before open
timeout: 30000, // ms before half-open
resetTimeout: 60000 // ms before close
};