FSC Integration Patterns — Developer Guidance
Use this skill when building or reviewing Apex-backed integrations that move financial data into or out of FSC Financial Services Cloud objects. It covers daily batch reconciliation from core banking systems, real-time custodian feed handling via the FSC Integrations API, market data price pipelines, and payment transaction flows. It does not cover generic Salesforce REST/SOAP integration or MuleSoft platform setup unrelated to FSC financial objects.
Before Starting
Gather this context before working on anything in this domain:
- Namespace: Determine whether the org uses the managed-package FSC (
FinServ__ namespace) or Core FSC (no namespace). Object API names differ — FinServ__FinancialAccount__c vs FinancialAccount. All integration queries, upserts, and field references must use the correct prefix.
- Rollup-by-Lookup (RBL) status: In Wealth Management Custom Settings, check whether RBL is enabled for the integration user. This is the single most common source of row-lock failures on bulk FinancialHolding loads. It must be disabled for the integration user before any batch operation against FinancialHolding or FinancialAccount.
- Pattern required: Confirm whether the integration is (a) daily batch reconciliation, (b) real-time event-driven custodian updates, or (c) market data price feeds. Each requires a different Apex pattern and different governor limit budget.
- Volume expectations: Establish record counts per load. Anything above ~5,000 FinancialHolding rows per run requires Bulk API 2.0 job semantics rather than synchronous DML.
Core Concepts
FSC Integrations API and Remote Call-In
The FSC Integrations API supports a Remote Call-In pattern for real-time custodian updates. External systems POST enriched financial data payloads to a Salesforce REST endpoint; Apex handler classes parse, validate, and upsert to FSC objects in the same transaction. This pattern is appropriate when custodian systems can emit near-real-time webhooks and latency of seconds is acceptable. It is not appropriate for daily position reconciliation at scale — batch Bulk API is the right tool there.
Change Data Capture (CDC) works in the reverse direction: FSC object changes flow outward to downstream systems. CDC on FinancialAccount is appropriate for replicating Salesforce-side changes (advisor notes, risk profile updates) back to a core banking system. Platform Events suit cross-application process orchestration — for example, notifying a downstream risk system when a new account is opened.
Bulk API Batch Loads for Daily Reconciliation
Core banking and custodian systems typically produce end-of-day position files. The standard pattern uses MuleSoft BIAN-canonical integration templates (or an equivalent ETL) to transform these files into Bulk API 2.0 ingest jobs targeting FinancialAccount and FinancialHolding. Bulk API 2.0 processes records in parallel server-side batches of up to 10,000 rows, does not consume synchronous Apex CPU, and provides job-level success/failure results that are safe to inspect asynchronously.
Key constraint: FinancialHolding records share a parent FinancialAccount. Concurrent Bulk API batches that touch holdings with the same parent will contend for the parent row lock if any trigger or process fires a rollup recalculation during the load. This is why RBL must be disabled for the integration user and DPE-based post-load recalculation must be scheduled separately.
Scheduled and Batch Apex for Market Data Feeds
Market data feeds update CurrentValue (and related price fields) on FinancialHolding records after each trading day. The correct Apex pattern is a Schedulable that enqueues a Batchable class. The batch queries holdings needing price updates, makes callouts to the market data vendor in execute() chunks, and updates the records. Synchronous callouts from DML-heavy triggers are prohibited by the Apex callout-after-DML restriction and will fail at runtime with a System.CalloutException. Post-load DPE aggregation should recalculate portfolio totals after the batch completes, not inline.
Common Patterns
Pattern A: Daily Custodian Reconciliation via Bulk API
When to use: End-of-day position file from Schwab, Fidelity, or similar; file volume 5,000–2,000,000 FinancialHolding rows per night.
How it works:
- Disable RBL for the integration user in Wealth Management Custom Settings (via Named Credential–secured connected app with a dedicated integration profile).
- ETL/MuleSoft transforms custodian position file into Bulk API 2.0 ingest job against
FinancialHolding, using ExternalId or AccountNumber as the upsert key.
- Monitor job via Bulk API job status endpoint; log failures to a custom object for reconciliation review.
- After job completes, enqueue a Schedulable/Batchable to trigger DPE recalculation of household and account-level rollups.
- Re-enable RBL (or leave it disabled if nightly runs are continuous).
Why not synchronous Apex upsert: Bulk loads of this volume exceed DMLException transaction limits, trigger callout-after-DML restrictions, and cause rollup row-lock contention if RBL is active.
Pattern B: Real-Time Custodian Update via FSC Integrations API
When to use: Custodian or payment processor can emit near-real-time webhooks; fewer than a few hundred records per event; latency of 2–5 seconds is acceptable.
How it works:
- External system authenticates to Salesforce via Connected App (OAuth 2.0 JWT Bearer).
- POST payload to a custom REST endpoint backed by an
@RestResource Apex class.
- Handler class validates payload, applies idempotency check (query for existing record by external ID before insert), and upserts to
FinancialAccount or FinancialHolding.
- Platform Event is published on success to notify downstream processes.
Why not inbound Bulk API for real-time: Bulk API jobs are asynchronous with variable processing delay; they are not suitable for sub-second transactional confirmation.
Pattern C: Market Data Price Feed via Scheduled Batch
When to use: Daily or intraday CurrentValue updates on FinancialHolding; external market data vendor provides REST price endpoint.
How it works:
Schedulable class fires at market close (or configured interval).
- Enqueues
Batchable with scope of 50–100 holdings per chunk (tuned to callout limits).
- Each
execute() chunk calls market data endpoint, maps prices to holdings, performs DML update.
finish() method publishes Platform Event to trigger downstream DPE recalculation.
Decision Guidance
| Situation |
Recommended Approach |
Reason |
| Daily end-of-day position file, 10k–2M rows |
Bulk API 2.0 ingest job (via MuleSoft or ETL) |
Scale, parallelism, no Apex CPU cost |
| Real-time custodian webhook, <500 records |
FSC Integrations API (Remote Call-In, @RestResource) |
Low latency, transactional confirmation |
| FSC changes replicate to core banking |
Change Data Capture on FinancialAccount |
Native Salesforce event emission, no polling |
| Cross-app process notification (new account opened) |
Platform Events |
Decoupled, durable, retry-safe |
| Daily market data price updates |
Scheduled Batch Apex with callouts |
Avoids callout-after-DML, respects callout limits |
| Post-load rollup recalculation |
Data Processing Engine (DPE) |
Avoids RBL row-lock contention at scale |
Recommended Workflow
Step-by-step instructions for an AI agent or practitioner working on this task:
- Confirm org namespace and pattern scope — determine managed-package vs Core FSC, identify which FSC objects are targets, and confirm whether the integration is batch, real-time, or market-data-feed.
- Check Rollup-by-Lookup configuration — before any bulk load design, verify RBL status for the integration user in Wealth Management Custom Settings. Document whether it needs to be disabled before the load and re-enabled (or replaced with DPE) after.
- Select the integration pattern — use the Decision Guidance table to choose between Bulk API batch, Remote Call-In, CDC, Platform Events, or Scheduled Batch. Do not mix synchronous callouts with DML-heavy trigger paths.
- Implement Apex with idempotency — for Remote Call-In patterns, query for existing records by external ID before upsert. For batch patterns, implement
Database.Stateful if state must persist across chunks and use Database.executeBatch with appropriate scope size.
- Validate governor limit budget — confirm callout count (max 100 per transaction), heap size, and CPU time are within limits for the chosen scope. For Bulk API jobs, confirm job concurrency limits (10 open jobs per org).
- Test with realistic data volume — unit tests must cover both the happy path and the failure path (invalid payload, duplicate external ID, RBL still enabled). Integration tests should use a Bulk API sandbox load of at least 10,000 records to surface row-lock behavior.
- Wire post-load DPE recalculation — after any batch load, schedule DPE to recompute household rollups. Verify rollup correctness against a known-good custodian snapshot before signing off.
Review Checklist
Run through these before marking work in this area complete:
Salesforce-Specific Gotchas
Non-obvious platform behaviors that cause real production problems:
- RBL row-lock on concurrent FinancialHolding writes — When Rollup-by-Lookup is enabled, every write to a FinancialHolding record triggers a recalculation that acquires a row-lock on the parent FinancialAccount. Bulk API processes batches in parallel, so multiple batches touching holdings under the same account contend for the same parent lock, causing
UNABLE_TO_LOCK_ROW errors. Fix: disable RBL for the integration user before the load; recalculate via DPE afterward.
- Callout-after-DML restriction on trigger paths — Apex prohibits callouts after DML has been performed in the same transaction. Any trigger on FinancialHolding that attempts to call a market data or custodian endpoint after an upsert will throw
System.CalloutException: You have uncommitted work pending. Fix: move callouts to a Queueable or Schedulable/Batchable class that runs in a fresh transaction.
- Namespace mismatch between managed-package and Core FSC — Queries, field references, and SOQL written for one FSC deployment type fail silently or throw
System.QueryException in another. Managed-package orgs use FinServ__FinancialAccount__c; Core FSC orgs use FinancialAccount. Always confirm namespace at the start of any integration work and parameterize object/field references.
Output Artifacts
| Artifact |
Description |
| Integration pattern recommendation |
Pattern selection (Bulk API / Remote Call-In / CDC / Platform Events / Scheduled Batch) with rationale |
| RBL pre/post-load checklist |
Steps to disable RBL, run load, schedule DPE recalculation |
| Apex batch or scheduled class |
Batchable + Schedulable implementation for market data or reconciliation loads |
| Remote Call-In handler |
@RestResource Apex class with idempotency check and error handling |
Related Skills
admin/financial-account-setup — configure FinancialAccount and FinancialHolding data model, roles, and household rollup settings before wiring integration
integration/event-driven-architecture-patterns — general Platform Events and CDC patterns when FSC-specific guidance is not required
apex/fsl-integration-patterns — FSL-specific integration patterns for field service; separate domain from FSC financial integrations
1---2name: fsc-integration-patterns-dev3description: Use this skill when designing or implementing FSC-specific integration: core banking data sync, custodian feeds (Schwab/Fidelity), market data pipelines, or payment processing wired to FSC Financial objects. Triggers: syncing FinancialAccount or FinancialHolding records from a core banking system, integrating a custodian data feed into FSC Wealth Management, market data prices updating CurrentValue on FinancialHolding, payment transactions flowing into FSC from an external ledger. NOT for a one-time bulk load of FSC records — use data/financial-account-migration. NOT for IRR, TWR or rollup recalculation — use apex/fsc-financial-calculations.4---56# FSC Integration Patterns — Developer Guidance78Use this skill when building or reviewing Apex-backed integrations that move financial data into or out of FSC Financial Services Cloud objects. It covers daily batch reconciliation from core banking systems, real-time custodian feed handling via the FSC Integrations API, market data price pipelines, and payment transaction flows. It does not cover generic Salesforce REST/SOAP integration or MuleSoft platform setup unrelated to FSC financial objects.910---1112## Before Starting1314Gather this context before working on anything in this domain:1516- **Namespace**: Determine whether the org uses the managed-package FSC (`FinServ__` namespace) or Core FSC (no namespace). Object API names differ — `FinServ__FinancialAccount__c` vs `FinancialAccount`. All integration queries, upserts, and field references must use the correct prefix.17- **Rollup-by-Lookup (RBL) status**: In Wealth Management Custom Settings, check whether RBL is enabled for the integration user. This is the single most common source of row-lock failures on bulk FinancialHolding loads. It must be disabled for the integration user before any batch operation against FinancialHolding or FinancialAccount.18- **Pattern required**: Confirm whether the integration is (a) daily batch reconciliation, (b) real-time event-driven custodian updates, or (c) market data price feeds. Each requires a different Apex pattern and different governor limit budget.19- **Volume expectations**: Establish record counts per load. Anything above ~5,000 FinancialHolding rows per run requires Bulk API 2.0 job semantics rather than synchronous DML.2021---2223## Core Concepts2425### FSC Integrations API and Remote Call-In2627The FSC Integrations API supports a Remote Call-In pattern for real-time custodian updates. External systems POST enriched financial data payloads to a Salesforce REST endpoint; Apex handler classes parse, validate, and upsert to FSC objects in the same transaction. This pattern is appropriate when custodian systems can emit near-real-time webhooks and latency of seconds is acceptable. It is not appropriate for daily position reconciliation at scale — batch Bulk API is the right tool there.2829Change Data Capture (CDC) works in the reverse direction: FSC object changes flow outward to downstream systems. CDC on `FinancialAccount` is appropriate for replicating Salesforce-side changes (advisor notes, risk profile updates) back to a core banking system. Platform Events suit cross-application process orchestration — for example, notifying a downstream risk system when a new account is opened.3031### Bulk API Batch Loads for Daily Reconciliation3233Core banking and custodian systems typically produce end-of-day position files. The standard pattern uses MuleSoft BIAN-canonical integration templates (or an equivalent ETL) to transform these files into Bulk API 2.0 ingest jobs targeting `FinancialAccount` and `FinancialHolding`. Bulk API 2.0 processes records in parallel server-side batches of up to 10,000 rows, does not consume synchronous Apex CPU, and provides job-level success/failure results that are safe to inspect asynchronously.3435Key constraint: `FinancialHolding` records share a parent `FinancialAccount`. Concurrent Bulk API batches that touch holdings with the same parent will contend for the parent row lock if any trigger or process fires a rollup recalculation during the load. This is why RBL must be disabled for the integration user and DPE-based post-load recalculation must be scheduled separately.3637### Scheduled and Batch Apex for Market Data Feeds3839Market data feeds update `CurrentValue` (and related price fields) on `FinancialHolding` records after each trading day. The correct Apex pattern is a `Schedulable` that enqueues a `Batchable` class. The batch queries holdings needing price updates, makes callouts to the market data vendor in `execute()` chunks, and updates the records. Synchronous callouts from DML-heavy triggers are prohibited by the Apex callout-after-DML restriction and will fail at runtime with a `System.CalloutException`. Post-load DPE aggregation should recalculate portfolio totals after the batch completes, not inline.4041---4243## Common Patterns4445### Pattern A: Daily Custodian Reconciliation via Bulk API4647**When to use:** End-of-day position file from Schwab, Fidelity, or similar; file volume 5,000–2,000,000 FinancialHolding rows per night.4849**How it works:**501. Disable RBL for the integration user in Wealth Management Custom Settings (via Named Credential–secured connected app with a dedicated integration profile).512. ETL/MuleSoft transforms custodian position file into Bulk API 2.0 ingest job against `FinancialHolding`, using `ExternalId` or `AccountNumber` as the upsert key.523. Monitor job via Bulk API job status endpoint; log failures to a custom object for reconciliation review.534. After job completes, enqueue a Schedulable/Batchable to trigger DPE recalculation of household and account-level rollups.545. Re-enable RBL (or leave it disabled if nightly runs are continuous).5556**Why not synchronous Apex upsert:** Bulk loads of this volume exceed `DMLException` transaction limits, trigger callout-after-DML restrictions, and cause rollup row-lock contention if RBL is active.5758### Pattern B: Real-Time Custodian Update via FSC Integrations API5960**When to use:** Custodian or payment processor can emit near-real-time webhooks; fewer than a few hundred records per event; latency of 2–5 seconds is acceptable.6162**How it works:**631. External system authenticates to Salesforce via Connected App (OAuth 2.0 JWT Bearer).642. POST payload to a custom REST endpoint backed by an `@RestResource` Apex class.653. Handler class validates payload, applies idempotency check (query for existing record by external ID before insert), and upserts to `FinancialAccount` or `FinancialHolding`.664. Platform Event is published on success to notify downstream processes.6768**Why not inbound Bulk API for real-time:** Bulk API jobs are asynchronous with variable processing delay; they are not suitable for sub-second transactional confirmation.6970### Pattern C: Market Data Price Feed via Scheduled Batch7172**When to use:** Daily or intraday `CurrentValue` updates on FinancialHolding; external market data vendor provides REST price endpoint.7374**How it works:**751. `Schedulable` class fires at market close (or configured interval).762. Enqueues `Batchable` with scope of 50–100 holdings per chunk (tuned to callout limits).773. Each `execute()` chunk calls market data endpoint, maps prices to holdings, performs DML update.784. `finish()` method publishes Platform Event to trigger downstream DPE recalculation.7980---8182## Decision Guidance8384| Situation | Recommended Approach | Reason |85|---|---|---|86| Daily end-of-day position file, 10k–2M rows | Bulk API 2.0 ingest job (via MuleSoft or ETL) | Scale, parallelism, no Apex CPU cost |87| Real-time custodian webhook, <500 records | FSC Integrations API (Remote Call-In, `@RestResource`) | Low latency, transactional confirmation |88| FSC changes replicate to core banking | Change Data Capture on FinancialAccount | Native Salesforce event emission, no polling |89| Cross-app process notification (new account opened) | Platform Events | Decoupled, durable, retry-safe |90| Daily market data price updates | Scheduled Batch Apex with callouts | Avoids callout-after-DML, respects callout limits |91| Post-load rollup recalculation | Data Processing Engine (DPE) | Avoids RBL row-lock contention at scale |9293---9495## Recommended Workflow9697Step-by-step instructions for an AI agent or practitioner working on this task:98991. **Confirm org namespace and pattern scope** — determine managed-package vs Core FSC, identify which FSC objects are targets, and confirm whether the integration is batch, real-time, or market-data-feed.1002. **Check Rollup-by-Lookup configuration** — before any bulk load design, verify RBL status for the integration user in Wealth Management Custom Settings. Document whether it needs to be disabled before the load and re-enabled (or replaced with DPE) after.1013. **Select the integration pattern** — use the Decision Guidance table to choose between Bulk API batch, Remote Call-In, CDC, Platform Events, or Scheduled Batch. Do not mix synchronous callouts with DML-heavy trigger paths.1024. **Implement Apex with idempotency** — for Remote Call-In patterns, query for existing records by external ID before upsert. For batch patterns, implement `Database.Stateful` if state must persist across chunks and use `Database.executeBatch` with appropriate scope size.1035. **Validate governor limit budget** — confirm callout count (max 100 per transaction), heap size, and CPU time are within limits for the chosen scope. For Bulk API jobs, confirm job concurrency limits (10 open jobs per org).1046. **Test with realistic data volume** — unit tests must cover both the happy path and the failure path (invalid payload, duplicate external ID, RBL still enabled). Integration tests should use a Bulk API sandbox load of at least 10,000 records to surface row-lock behavior.1057. **Wire post-load DPE recalculation** — after any batch load, schedule DPE to recompute household rollups. Verify rollup correctness against a known-good custodian snapshot before signing off.106107---108109## Review Checklist110111Run through these before marking work in this area complete:112113- [ ] Integration user profile has RBL disabled in Wealth Management Custom Settings before any bulk FinancialHolding load114- [ ] Bulk API 2.0 job is used for loads above ~5,000 records (not synchronous DML)115- [ ] No synchronous callouts inside triggers or transaction-heavy DML paths on FinancialHolding116- [ ] Idempotency check (external ID query before upsert) present in all Remote Call-In handlers117- [ ] DPE recalculation scheduled as a separate step after bulk loads complete118- [ ] Connected App uses Named Credential and OAuth 2.0 JWT Bearer (not username/password)119- [ ] Apex batch scope size tuned to keep callout count + DML rows within per-transaction limits120121---122123## Salesforce-Specific Gotchas124125Non-obvious platform behaviors that cause real production problems:1261271. **RBL row-lock on concurrent FinancialHolding writes** — When Rollup-by-Lookup is enabled, every write to a FinancialHolding record triggers a recalculation that acquires a row-lock on the parent FinancialAccount. Bulk API processes batches in parallel, so multiple batches touching holdings under the same account contend for the same parent lock, causing `UNABLE_TO_LOCK_ROW` errors. Fix: disable RBL for the integration user before the load; recalculate via DPE afterward.1282. **Callout-after-DML restriction on trigger paths** — Apex prohibits callouts after DML has been performed in the same transaction. Any trigger on FinancialHolding that attempts to call a market data or custodian endpoint after an upsert will throw `System.CalloutException: You have uncommitted work pending`. Fix: move callouts to a Queueable or Schedulable/Batchable class that runs in a fresh transaction.1293. **Namespace mismatch between managed-package and Core FSC** — Queries, field references, and SOQL written for one FSC deployment type fail silently or throw `System.QueryException` in another. Managed-package orgs use `FinServ__FinancialAccount__c`; Core FSC orgs use `FinancialAccount`. Always confirm namespace at the start of any integration work and parameterize object/field references.130131---132133## Output Artifacts134135| Artifact | Description |136|---|---|137| Integration pattern recommendation | Pattern selection (Bulk API / Remote Call-In / CDC / Platform Events / Scheduled Batch) with rationale |138| RBL pre/post-load checklist | Steps to disable RBL, run load, schedule DPE recalculation |139| Apex batch or scheduled class | Batchable + Schedulable implementation for market data or reconciliation loads |140| Remote Call-In handler | `@RestResource` Apex class with idempotency check and error handling |141142---143144## Related Skills145146- `admin/financial-account-setup` — configure FinancialAccount and FinancialHolding data model, roles, and household rollup settings before wiring integration147- `integration/event-driven-architecture-patterns` — general Platform Events and CDC patterns when FSC-specific guidance is not required148- `apex/fsl-integration-patterns` — FSL-specific integration patterns for field service; separate domain from FSC financial integrations