CRM Software Design Document (SDD)
Contact Relationship Management System
Document Information
- Version: 1.0
- Date: October 2025
- Status: Draft
- References: crm-requirements-document.md
Table of Contents
- System Architecture
- Component Design
- Data Architecture
- API Design
- Integration Architecture
- Security Architecture
- Performance Design
- Deployment Architecture
System Architecture
High-Level Architecture
Architecture Principles
- Microservices Pattern: Each major feature is a separate service
- Event-Driven: Asynchronous processing for enrichment and viral mechanics
- API-First: All functionality exposed through RESTful APIs
- Cache-Heavy: Redis caching for performance
- Cloud-Native: Designed for GCP services
Component Design
Contact Service
Purpose: Core CRUD operations for contact management
Key Components:
// src/services/contact_service.rs
pub struct ContactService {
db_pool: PgPool,
cache: RedisClient,
event_publisher: PubSubClient,
}
pub struct Contact {
pub id: Uuid,
pub user_id: Uuid,
pub email: String,
pub name: String,
pub company: Option<String>,
pub enrichment_status: EnrichmentStatus,
pub social_profiles: HashMap<String, String>,
pub custom_fields: JsonValue,
pub tags: Vec<String>,
pub relationship_stage: RelationshipStage,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
Key Methods:
create_contact(): Create with duplicate detectionbulk_import(): Import with progress trackingsearch_contacts(): Full-text search with filtersmerge_contacts(): Intelligent duplicate merging
Enrichment Service
Purpose: AI-powered contact data enrichment
Architecture:
// src/services/enrichment_service.rs
pub struct EnrichmentService {
providers: Vec<Box<dyn EnrichmentProvider>>,
cache: RedisClient,
rate_limiter: RateLimiter,
}
#[async_trait]
pub trait EnrichmentProvider {
async fn enrich(&self, contact: &Contact) -> Result<EnrichmentData>;
fn provider_name(&self) -> &str;
fn cost_per_enrichment(&self) -> f64;
}
pub struct EnrichmentOrchestrator {
queue: PubSubSubscriber,
service: EnrichmentService,
credit_manager: CreditManager,
}
Enrichment Flow:
- Contact created/imported → Publish enrichment event
- Orchestrator consumes event → Check user credits
- Query multiple providers in parallel
- Merge and deduplicate data
- Update contact with enriched data
- Award credits for data contribution
Social Graph Service
Purpose: Relationship mapping and network analysis
Graph Model:
// src/services/social_graph_service.rs
pub struct SocialGraphService {
graph_db: GraphDatabase, // Could use PostgreSQL with recursive CTEs
cache: RedisClient,
analytics: GraphAnalytics,
}
pub struct Relationship {
pub from_contact_id: Uuid,
pub to_contact_id: Uuid,
pub relationship_type: RelationType,
pub strength: f32, // 0.0 to 1.0
pub interaction_count: i32,
pub last_interaction: DateTime<Utc>,
}
pub struct NetworkPath {
pub nodes: Vec<Uuid>,
pub total_distance: i32,
pub connection_quality: f32,
}
Key Algorithms:
- Dijkstra's algorithm for shortest path
- PageRank for influence scoring
- Community detection for clustering
- Relationship strength calculation
Communication Hub
Purpose: Unified communication tracking and analytics
Design:
// src/services/communication_hub.rs
pub struct CommunicationHub {
email_integrations: Vec<EmailProvider>,
sms_gateway: SmsGateway,
message_queue: MessageQueue,
analytics: CommunicationAnalytics,
}
pub struct Communication {
pub id: Uuid,
pub contact_id: Uuid,
pub channel: CommunicationChannel,
pub direction: Direction, // Inbound/Outbound
pub content: String,
pub sentiment_score: f32,
pub timestamp: DateTime<Utc>,
}
Viral Mechanics Engine
Purpose: Drive viral growth through gamification and incentives
Components:
// src/services/viral_engine.rs
pub struct ViralEngine {
credit_system: CreditSystem,
gamification: GamificationEngine,
analytics: ViralAnalytics,
}
pub struct ViralAction {
pub action_type: ActionType, // Import, Share, Referral, etc.
pub user_id: Uuid,
pub credits_earned: i32,
pub xp_earned: i32,
pub triggered_achievements: Vec<Achievement>,
}
pub struct ViralMetrics {
pub k_factor: f32,
pub viral_cycle_time: Duration,
pub conversion_rate: f32,
}
Data Architecture
Primary Database Schema
-- Core Contacts Table
CREATE TABLE contacts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id),
email VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
company VARCHAR(255),
title VARCHAR(255),
phone VARCHAR(50),
enrichment_status VARCHAR(50) DEFAULT 'pending',
enrichment_data JSONB,
social_profiles JSONB,
custom_fields JSONB,
tags TEXT[],
relationship_stage VARCHAR(50),
source VARCHAR(100),
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT unique_user_email UNIQUE(user_id, email)
);
-- Social Graph Relationships
CREATE TABLE relationships (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
from_contact_id UUID REFERENCES contacts(id),
to_contact_id UUID REFERENCES contacts(id),
relationship_type VARCHAR(50),
strength DECIMAL(3,2),
interaction_count INTEGER DEFAULT 0,
last_interaction TIMESTAMPTZ,
metadata JSONB,
created_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT unique_relationship UNIQUE(from_contact_id, to_contact_id)
);
-- Communication History
CREATE TABLE communications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
contact_id UUID REFERENCES contacts(id),
user_id UUID REFERENCES users(id),
channel VARCHAR(50),
direction VARCHAR(10),
subject TEXT,
content TEXT,
sentiment_score DECIMAL(3,2),
metadata JSONB,
occurred_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Viral Mechanics
CREATE TABLE viral_actions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
action_type VARCHAR(50),
credits_earned INTEGER,
xp_earned INTEGER,
metadata JSONB,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Enrichment Credits
CREATE TABLE user_credits (
user_id UUID PRIMARY KEY REFERENCES users(id),
balance INTEGER DEFAULT 100,
lifetime_earned INTEGER DEFAULT 100,
lifetime_spent INTEGER DEFAULT 0,
updated_at TIMESTAMPTZ DEFAULT NOW()
);
Caching Strategy
Redis Cache Structure:
# Contact Cache
contact:{user_id}:{contact_id} -> Contact JSON (TTL: 1 hour)
# Search Cache
search:{user_id}:{query_hash} -> Contact IDs (TTL: 15 minutes)
# Social Graph Cache
graph:paths:{from_id}:{to_id} -> Path JSON (TTL: 1 hour)
graph:network:{user_id} -> Network Stats (TTL: 30 minutes)
# Enrichment Cache
enrichment:{email_hash} -> Enrichment Data (TTL: 7 days)
# User Credits Cache
credits:{user_id} -> Credit Balance (TTL: 5 minutes)
API Design
RESTful Endpoints
Contact Management:
POST /api/crm/contacts Create contact
GET /api/crm/contacts List contacts (paginated)
GET /api/crm/contacts/:id Get contact details
PUT /api/crm/contacts/:id Update contact
DELETE /api/crm/contacts/:id Delete contact
POST /api/crm/contacts/bulk-import Import contacts
POST /api/crm/contacts/merge Merge duplicates
GET /api/crm/contacts/search Search contacts
Enrichment:
POST /api/crm/enrichment/enrich/:id Trigger enrichment
GET /api/crm/enrichment/status/:id Check enrichment status
GET /api/crm/enrichment/credits Get credit balance
POST /api/crm/enrichment/verify Verify and earn credits
Social Graph:
GET /api/crm/graph/network/:id Get contact's network
GET /api/crm/graph/path Find path between contacts
GET /api/crm/graph/influence/:id Get influence score
POST /api/crm/graph/introduce Request introduction
Communication Hub:
GET /api/crm/communications/:contact Get communication history
POST /api/crm/communications/track Track communication
GET /api/crm/communications/analytics Communication analytics
POST /api/crm/communications/remind Set reminder
Viral Mechanics:
GET /api/crm/viral/stats Get viral metrics
POST /api/crm/viral/refer Create referral
GET /api/crm/viral/leaderboard Get leaderboard
GET /api/crm/viral/achievements Get achievements
GraphQL Schema (Optional)
type Contact {
id: ID!
name: String!
email: String!
company: String
enrichmentData: EnrichmentData
relationships: [Relationship!]!
communications(limit: Int, offset: Int): [Communication!]!
networkStats: NetworkStats!
}
type Query {
contact(id: ID!): Contact
contacts(filter: ContactFilter, limit: Int, offset: Int): ContactConnection!
shortestPath(fromId: ID!, toId: ID!): NetworkPath
myViralStats: ViralStats!
}
type Mutation {
createContact(input: CreateContactInput!): Contact!
enrichContact(id: ID!): EnrichmentJob!
requestIntroduction(fromId: ID!, toId: ID!, message: String): IntroductionRequest!
}
Integration Architecture
Platform Integration Points
1. Authentication Integration:
// Shared with main platform
pub trait AuthProvider {
async fn validate_token(&self, token: &str) -> Result<User>;
async fn get_user_permissions(&self, user_id: Uuid) -> Result<Permissions>;
}
2. Event Bus Integration:
# Pub/Sub Topics
topics:
- contact.created
- contact.enriched
- viral.action.completed
- introduction.requested
- credits.earned
3. Billing Integration:
// Shared billing service
pub trait BillingProvider {
async fn check_subscription(&self, user_id: Uuid) -> Result<Subscription>;
async fn track_usage(&self, user_id: Uuid, feature: &str, amount: i32);
}
External Service Integrations
Enrichment Providers:
- Clearbit: Company and person data
- FullContact: Social profiles
- Hunter.io: Email verification
- Custom scrapers: LinkedIn, Twitter
Communication Providers:
- SendGrid: Email tracking
- Twilio: SMS gateway
- Gmail API: Email sync
- Outlook API: Calendar/email sync
Security Architecture
Data Protection
Encryption:
- At rest: AES-256 for PII fields
- In transit: TLS 1.3 minimum
- Field-level encryption for sensitive data
Access Control:
pub enum ContactPermission {
ViewOwn,
ViewTeam,
EditOwn,
EditTeam,
Delete,
Export,
ShareExternal,
}
pub struct ContactAccessControl {
pub fn can_access(&self, user: &User, contact: &Contact, permission: ContactPermission) -> bool {
// Implement RBAC logic
}
}
Privacy Controls
Data Minimization:
- Store only necessary data
- Automatic PII purging after retention period
- Anonymization for analytics
Consent Management:
pub struct ConsentManager {
pub fn record_consent(&self, contact_id: Uuid, consent_type: ConsentType);
pub fn check_consent(&self, contact_id: Uuid, action: &str) -> bool;
pub fn withdraw_consent(&self, contact_id: Uuid, consent_type: ConsentType);
}
Performance Design
Optimization Strategies
1. Database Optimization:
- Composite indexes on (user_id, email)
- Partial indexes for active contacts
- Materialized views for analytics
- Connection pooling with pgbouncer
2. Caching Strategy:
- Write-through cache for contacts
- Cache-aside for enrichment data
- Distributed caching with Redis Cluster
- Cache warming for popular queries
3. Async Processing:
- Background enrichment jobs
- Batch import processing
- Deferred analytics calculation
- Event-driven viral tracking
4. Query Optimization:
-- Optimized contact search with FTS
CREATE INDEX idx_contacts_search ON contacts
USING gin(to_tsvector('english', name || ' ' || email || ' ' || company));
-- Efficient relationship queries
CREATE INDEX idx_relationships_graph ON relationships(from_contact_id, to_contact_id)
INCLUDE (strength, relationship_type);
Scalability Considerations
Horizontal Scaling:
- Stateless services for easy scaling
- Read replicas for PostgreSQL
- Sharding strategy for large datasets
- Auto-scaling based on CPU/memory
Performance Targets:
- Contact search: <100ms for 1M contacts
- Enrichment: <2s average per contact
- Graph traversal: <500ms for 3 degrees
- API response: <200ms p95
Deployment Architecture
Container Structure
# Base image for Rust services
FROM rust:1.75-alpine AS builder
WORKDIR /app
COPY cargo.toml Cargo.lock ./
COPY crm-module/src ./src
RUN cargo build --release
FROM alpine:3.19
RUN apk add --no-cache ca-certificates
COPY --from=builder /app/target/release/crm-service /usr/local/bin/
EXPOSE 8080
CMD ["crm-service"]
Kubernetes Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: crm-contact-service
spec:
replicas: 3
selector:
matchLabels:
app: crm-contact-service
template:
metadata:
labels:
app: crm-contact-service
spec:
containers:
- name: contact-service
image: gcr.io/project/crm-contact-service:latest
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: crm-secrets
key: database-url
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
Monitoring & Observability
Metrics:
- Contact creation rate
- Enrichment success rate
- API latency percentiles
- Cache hit rates
- Viral K-factor
Logging:
use tracing::{info, error, instrument};
#[instrument]
pub async fn create_contact(&self, input: CreateContactInput) -> Result<Contact> {
info!("Creating contact for user {}", input.user_id);
// Implementation
}
Distributed Tracing:
- OpenTelemetry integration
- Trace ID propagation
- Performance bottleneck identification
Testing Strategy
Unit Tests
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_contact_creation() {
let service = ContactService::new_test();
let contact = service.create_contact(/*...*/).await.unwrap();
assert_eq!(contact.email, "test@example.com");
}
}
Integration Tests
- Test against real PostgreSQL
- Mock external services
- Test event publishing
- Verify cache behavior
Performance Tests
- Load test with k6
- Benchmark critical paths
- Stress test enrichment queue
- Graph traversal performance
Migration Strategy
From Existing System
- Export existing contacts
- Transform to new schema
- Batch import with deduplication
- Gradual enrichment rollout
- Parallel run for validation
Database Migrations
-- Migration 001: Initial schema
CREATE TABLE contacts (...);
-- Migration 002: Add viral mechanics
CREATE TABLE viral_actions (...);
-- Migration 003: Performance indexes
CREATE INDEX CONCURRENTLY ...;
Risk Mitigation
Technical Risks
- Enrichment API Rate Limits: Multiple providers, caching, backoff
- Data Quality: Verification system, community validation
- Scale: Designed for 10M+ contacts from day one
- Privacy: GDPR compliance built-in
Business Risks
- Viral Growth Control: Circuit breakers for exponential growth
- Credit System Abuse: Fraud detection, rate limiting
- Data Accuracy: Multiple source verification
- Competition: Unique value proposition focus