encyMinutes: 15 | 30 | 60 | 1440;
enableWriteBack: boolean;
}
class SyncConfigValidator {
private readonly MAX_FIELDS_PER_OBJECT = 50;
private readonly ALLOWED_FREQUENCIES = [15, 30, 60, 1440];
validate(config: SyncObjectConfig): { valid: boolean; errors: string[] } {
const errors: string[] = [];
if (config.fields.length > this.MAX_FIELDS_PER_OBJECT) {
errors.push(`Field count exceeds limit. Found: ${config.fields.length}, Max: ${this.MAX_FIELDS_PER_OBJECT}`);
}
if (!this.ALLOWED_FREQUENCIES.includes(config.syncFrequencyMinutes)) {
errors.push(`Invalid sync frequency. Must be one of: ${this.ALLOWED_FREQUENCIES.join(', ')}`);
}
const primaryKeys = config.fields.filter(f => f.isPrimaryKey);
if (primaryKeys.length !== 1) {
errors.push('Exactly one primary key field must be defined.');
}
const duplicateFields = config.fields.filter((f, i, arr) =>
arr.findIndex(x => x.crmApiName === f.crmApiName) !== i
);
if (duplicateFields.length > 0) {
errors.push(`Duplicate field definitions detected: ${duplicateFields.map(f => f.crmApiName).join(', ')}`);
}
return { valid: errors.length === 0, errors };
}
}
**Architecture Rationale**: Limiting fields to 50 per object aligns with Salesforce API payload optimization guidelines. Enforcing a single primary key prevents ambiguous record matching during write-back operations. Validating frequency against platform-supported intervals prevents configuration drift when the managed package updates.
### Step 2: Route Journey Triggers Based on Latency Requirements
Not all journey triggers should rely on synchronized data extensions. The trigger router evaluates the required freshness and routes to the appropriate ingestion mechanism.
```typescript
type TriggerStrategy = 'SYNC_DE' | 'PLATFORM_EVENT' | 'REST_API';
interface JourneyTriggerPayload {
recordId: string;
objectType: string;
requiredLatencyMs: number;
metadata: Record<string, unknown>;
}
class JourneyTriggerRouter {
private readonly SYNC_LATENCY_THRESHOLD_MS = 900000; // 15 minutes
resolveStrategy(payload: JourneyTriggerPayload): TriggerStrategy {
if (payload.requiredLatencyMs <= 5000) {
return 'PLATFORM_EVENT';
}
if (payload.requiredLatencyMs <= this.SYNC_LATENCY_THRESHOLD_MS) {
return 'REST_API';
}
return 'SYNC_DE';
}
generateEntrySourceConfig(strategy: TriggerStrategy): Record<string, unknown> {
const base = { entryEventName: 'JourneyEntry', version: 2 };
switch (strategy) {
case 'PLATFORM_EVENT':
return { ...base, sourceType: 'SalesforcePlatformEvent', eventBus: 'MC_Journey_Trigger__e' };
case 'REST_API':
return { ...base, sourceType: 'APIEvent', definitionKey: 'RealTimeJourneyEntry' };
case 'SYNC_DE':
return { ...base, sourceType: 'SalesforceDataExtension', filterLogic: 'SyncCycle' };
default:
throw new Error('Unsupported trigger strategy');
}
}
}
Architecture Rationale: Platform Events bypass sync cycles entirely, making them ideal for sub-5-second triggers. REST API ingestion handles the 5β15 minute window but requires careful governor limit management. Synchronized data extensions remain the most stable option for batch-oriented campaigns. Routing at the configuration layer prevents journey builders from accidentally attaching to stale data sources.
Step 3: Construct Write-Back Activity Payloads
Salesforce Activity write-backs require explicit field mapping and error handling. The payload builder ensures type safety and prevents malformed requests from consuming API calls.
interface ActivityWriteBackConfig {
targetObject: string;
recordIdField: string;
updateFields: Array<{ crmField: string; sfmcValue: string }>;
retryOnConflict: boolean;
}
class ActivityPayloadBuilder {
buildPayload(config: ActivityWriteBackConfig, sfmcRecord: Record<string, unknown>): Record<string, unknown> {
const payload: Record<string, unknown> = {
sObject: config.targetObject,
[config.recordIdField]: sfmcRecord[config.recordIdField]
};
config.updateFields.forEach(field => {
const value = sfmcRecord[field.sfmcValue];
if (value === undefined || value === null) {
throw new Error(`Missing required value for field: ${field.sfmcValue}`);
}
payload[field.crmField] = value;
});
if (config.retryOnConflict) {
payload._retryPolicy = { maxAttempts: 3, backoffMs: 2000 };
}
return payload;
}
}
Architecture Rationale: Explicit field mapping prevents silent overwrites when CRM field names change. Throwing on missing values fails fast during sandbox testing rather than consuming production API calls. The retry policy structure mirrors Salesforce's recommended idempotency patterns for write-back operations.
Pitfall Guide
1. The "Sync Everything" Trap
Explanation: Synchronizing entire CRM objects instead of curated field sets increases payload size, extends sync duration, and raises timeout probability during high CRM transaction volumes.
Fix: Audit every field against journey requirements. Sync only fields that directly influence segmentation, personalization, or write-back logic. Document excluded fields and the rationale.
2. Latency Blindness in Journey Triggers
Explanation: Assuming synchronized data extensions provide near-real-time data. Default sync cycles run on 30-minute intervals, causing journey triggers to fire on stale records.
Fix: Map latency requirements to ingestion strategy. Use Platform Events for sub-5-second triggers, REST API for 5β15 minutes, and synchronized DEs for batch campaigns. Validate sync timestamps in sandbox before deployment.
3. Field Mapping Drift
Explanation: CRM field renames or data type changes break synchronized data extensions without triggering platform alerts. Journeys continue to run but populate with null or mismatched values.
Fix: Implement a pre-deployment schema validation script that compares CRM field metadata against MC Connect sync configuration. Version control sync mappings and require peer review for field additions.
4. Integration User Over-Provisioning
Explanation: Granting the Integration User system administrator or broad object-level permissions increases security risk and complicates audit trails. Write-back failures often stem from missing field-level edit access, not object-level read access.
Fix: Apply least-privilege principles. Grant read access to synced objects, edit access only to fields used in Salesforce Activity write-backs, and API enabled status. Review permissions quarterly using Salesforce Setup Audit Trail.
5. Sandbox-to-Production Configuration Drift
Explanation: MC Connect configurations are environment-specific. Sandbox sync settings, field mappings, and Integration User assignments rarely mirror production exactly, causing journey failures during cutover.
Fix: Export sync configurations using Metadata API or Salesforce DX. Maintain configuration-as-code repositories. Run automated parity checks between environments before production deployment.
6. Treating Distributed Marketing as a Technical Toggle
Explanation: Distributed Marketing requires template governance, user training, and CRM role alignment. Enabling it without operational readiness causes template misuse, compliance violations, and support ticket spikes.
Fix: Treat Distributed Marketing as a change management initiative. Define template approval workflows, assign CRM user roles explicitly, and run pilot campaigns with a controlled agent group before org-wide rollout.
7. Ignoring Governor Limits on Write-Backs
Explanation: Salesforce Activity write-backs consume API calls and DML limits. High-volume journeys can exhaust governor limits, causing silent failures and data inconsistency.
Fix: Batch write-back operations where possible. Implement circuit breakers that pause journey execution when API error rates exceed 5%. Monitor Salesforce API usage dashboards daily during campaign peaks.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| Campaign triggers on CRM record creation with < 5s latency requirement | Platform Event + API Entry Source | Bypasses sync cycles entirely; guarantees real-time execution | High (requires Apex/Flow development, event bus monitoring) |
| Weekly nurture campaign based on CRM opportunity stage | Synchronized Data Extension + Salesforce Entry Source | Sync latency is acceptable; native platform stability reduces operational overhead | Low (native configuration, minimal API consumption) |
| Monthly compliance report requiring historical CRM snapshots | Scheduled File Import + Import Activity | Avoids continuous sync overhead; aligns with batch processing windows | Low (storage cost only, no API governor impact) |
| High-volume write-back to CRM contact records | Salesforce Activity with batched payload + circuit breaker | Prevents governor limit exhaustion; maintains data consistency under load | Medium (requires monitoring infrastructure, retry logic development) |
Configuration Template
// mc-connect-pipeline.config.ts
import { SyncObjectConfig, JourneyTriggerPayload, ActivityWriteBackConfig } from './types';
export const SYNC_CONFIGS: SyncObjectConfig[] = [
{
objectApiName: 'Contact',
fields: [
{ crmApiName: 'Id', sfmcDataType: 'Text', isPrimaryKey: true, syncDirection: 'CRM_TO_SFMC' },
{ crmApiName: 'Email', sfmcDataType: 'Text', isPrimaryKey: false, syncDirection: 'CRM_TO_SFMC' },
{ crmApiName: 'Status__c', sfmcDataType: 'Text', isPrimaryKey: false, syncDirection: 'CRM_TO_SFMC' }
],
syncFrequencyMinutes: 30,
enableWriteBack: true
}
];
export const TRIGGER_PAYLOAD: JourneyTriggerPayload = {
recordId: '003XXXXXXXXXXXX',
objectType: 'Contact',
requiredLatencyMs: 1800000, // 30 minutes
metadata: { campaignId: '701XXXXXXXXXXXX' }
};
export const WRITE_BACK_CONFIG: ActivityWriteBackConfig = {
targetObject: 'Contact',
recordIdField: 'Id',
updateFields: [
{ crmField: 'Status__c', sfmcValue: 'journey_status' }
],
retryOnConflict: true
};
Quick Start Guide
- Install and verify the MC Connect managed package in your Salesforce CRM environment. Confirm the Integration User has API access and appropriate object-level permissions.
- Configure synchronized data extensions for each CRM object in scope. Limit fields to journey requirements and set sync frequency based on latency tolerance.
- Run initial sync and validate data in Contact Builder. Verify row counts, field types, and primary key integrity before proceeding to journey design.
- Build journey triggers using the appropriate entry source. Test with synthetic records that match filter logic and verify trigger timing against sync cycles.
- Deploy write-back activities with explicit field mapping and error handling. Monitor API usage and governor limits during the first production campaign cycle.