SfSkills Domains Docs GitHub

Home / apex / fsc-integration-patterns-dev

fsc-integration-patterns-dev

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.

Open the skill folder on GitHub


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:


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:

  1. Disable RBL for the integration user in Wealth Management Custom Settings (via Named Credential–secured connected app with a dedicated integration profile).
  2. ETL/MuleSoft transforms custodian position file into Bulk API 2.0 ingest job against FinancialHolding, using ExternalId or AccountNumber as the upsert key.
  3. Monitor job via Bulk API job status endpoint; log failures to a custom object for reconciliation review.
  4. After job completes, enqueue a Schedulable/Batchable to trigger DPE recalculation of household and account-level rollups.
  5. 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:

  1. External system authenticates to Salesforce via Connected App (OAuth 2.0 JWT Bearer).
  2. POST payload to a custom REST endpoint backed by an @RestResource Apex class.
  3. Handler class validates payload, applies idempotency check (query for existing record by external ID before insert), and upserts to FinancialAccount or FinancialHolding.
  4. 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:

  1. Schedulable class fires at market close (or configured interval).
  2. Enqueues Batchable with scope of 50–100 holdings per chunk (tuned to callout limits).
  3. Each execute() chunk calls market data endpoint, maps prices to holdings, performs DML update.
  4. finish() method publishes Platform Event to trigger downstream DPE recalculation.

Decision Guidance

SituationRecommended ApproachReason
Daily end-of-day position file, 10k–2M rowsBulk API 2.0 ingest job (via MuleSoft or ETL)Scale, parallelism, no Apex CPU cost
Real-time custodian webhook, <500 recordsFSC Integrations API (Remote Call-In, @RestResource)Low latency, transactional confirmation
FSC changes replicate to core bankingChange Data Capture on FinancialAccountNative Salesforce event emission, no polling
Cross-app process notification (new account opened)Platform EventsDecoupled, durable, retry-safe
Daily market data price updatesScheduled Batch Apex with calloutsAvoids callout-after-DML, respects callout limits
Post-load rollup recalculationData Processing Engine (DPE)Avoids RBL row-lock contention at scale

Step-by-step instructions for an AI agent or practitioner working on this task:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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).
  6. 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.
  7. 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:

  1. 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.
  2. 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.
  3. 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

ArtifactDescription
Integration pattern recommendationPattern selection (Bulk API / Remote Call-In / CDC / Platform Events / Scheduled Batch) with rationale
RBL pre/post-load checklistSteps to disable RBL, run load, schedule DPE recalculation
Apex batch or scheduled classBatchable + Schedulable implementation for market data or reconciliation loads
Remote Call-In handler@RestResource Apex class with idempotency check and error handling

Package files