Salesforce — real-time CDC, writeback, and conflict policy
Phase 1 of the Salesforce connector is read-only on a daily schedule. Once you have mapping confidence, you can enable two new behaviors per mapping: real-time CDC (Salesforce → Turtini, in seconds instead of hours) and writeback (Turtini → Salesforce). Both are off by default — opt in mapping-by-mapping so you can roll them out carefully.
Real-time CDC (Change Data Capture):
Salesforce publishes a change event over its Pub/Sub gRPC API every time a record is created, updated, undeleted, or deleted. Turtini runs a per-org streaming worker that subscribes to those events and applies them to the same canonical / external collections your scheduled sync uses.
To enable for a mapping:
1. Settings → Integrations → Salesforce → Mappings
2. Open a mapping → flip "Real-time streaming" on
3. The worker enables the corresponding CDC channel (e.g. `/data/AccountChangeEvent`) on your Salesforce org's Pub/Sub stream
4. From that point, every change in Salesforce lands in Turtini in seconds — no waiting for the nightly sync
5. The worker checkpoints a `replayId` after every batch, so a restart picks up exactly where it stopped — no duplicate or skipped events
What CDC handles:
• Creates → write a new Turtini doc with `salesforceId` stamped
• Updates → patch the matching Turtini doc; per-field conflict policy applies (see below)
• Deletes → soft-delete on the Turtini side. Sets `salesforceDeletedAt` and clears active fields without removing the doc itself, so audit and references stay intact.
Writeback (Turtini → Salesforce):
For each mapping, you can independently enable `writebackEnabled` (every Turtini edit pushes to Salesforce) and `deleteWritebackEnabled` (deleting in Turtini deletes the matching Salesforce record).
To enable writeback:
1. Open a mapping → flip "Writeback to Salesforce" on
2. Pick which fields are writable — by default every mapped field is writable in both directions; uncheck the ones you'd rather keep Turtini-local
3. Optional: flip "Delete writeback" on so Turtini-side deletes propagate. Off by default — Turtini soft-deletes only.
4. Save. The next save on a Turtini doc with a matching `salesforceId` is pushed to Salesforce via the REST API; new docs without a `salesforceId` are inserted and stamped on success.
Per-field conflict policy (Phase 5):
When both sides edit the same field between syncs, the conflict policy decides who wins:
• `last-write-wins` (default) — whichever side wrote most recently keeps the value
• `salesforce-wins` — Salesforce always wins; Turtini edits to this field are overwritten on the next sync
• `turtini-wins` — Turtini always wins; CDC updates for this field are ignored
Conflict policy is set per-field on the mapping row. Common patterns:
• Owner-side fields (Stage, Owner) → `salesforce-wins` so sales discipline isn't accidentally undone in Turtini
• Operational fields (delivery status, internal notes) → `turtini-wins` so the operating team owns them
• Free text (descriptions) → `last-write-wins` so whoever edited last sticks
Bulk operations:
Turtini uses the Salesforce Bulk 2.0 API for initial backfills and for any sync that touches > 2,000 records — single REST writes for smaller jobs and ad-hoc writebacks. Both paths are logged to the connector's audit chain.
Soft-delete semantics:
`salesforceDeletedAt` is set on the Turtini doc when CDC reports a delete (and on the Salesforce record when `deleteWritebackEnabled` is on for that direction). Soft-deleted docs are filtered out of every list view but remain in the database — recover by clearing the field, or hard-delete from the Trash tab in Admin → Audit.
Limits and watchpoints:
• Pub/Sub gRPC has a 50 events-per-second cap per org by default — Turtini handles burst smoothing, but very high-throughput Salesforce orgs may want to file a Salesforce support ticket for a higher cap
• Writeback honors all your Salesforce validation rules — if a write fails because of a rule, the error surfaces on the Turtini doc and the doc gets flagged for review
• Worker restarts replay from the last checkpoint — at-least-once semantics. The same change can be applied twice in a tight window; the per-field idempotency keys make repeat applies harmless.
Where this runs:
The streaming worker runs in a Cloud Run service (`salesforce-cdc-worker`) per region, fanning events out to per-org streams. You can see the per-org connection status (live / disconnected / replaying) on Settings → Integrations → Salesforce; the audit chain in Admin → Audit shows every CDC apply and every writeback for the connector.