Building a working custom adapter is a few hundred lines of Apex plus standard Setup configuration. The hard work is mapping the backend semantics onto the framework's Table, Column, and Filter abstractions.
- Set up the Named Credential
Setup, Named Credentials. Create a Named Credential with the backend URL and auth profile. The custom adapter references this credential by name for every callout.
- Write the DataSource.Provider class
Extend DataSource.Provider. Declare capabilities, return a DataSource.Connection instance, and implement getAuthenticationCapabilities and getCapabilities.
- Write the DataSource.Connection class
Extend DataSource.Connection. Implement sync, query, search, upsertRows, deleteRows as needed. Translate framework callbacks into REST or SOAP calls to the backend.
- Register the custom adapter in Setup
Setup, External Data Sources. Click New, choose Type Custom Adapter, and select the Provider class. Save and click Validate and Sync.
- Sync External Objects and test
After sync, External Objects appear in Object Manager. Run a SOQL query against one, verify the backend call fires, and confirm the returned data matches expectations.
Top-level Apex class declaring capabilities and returning a Connection.
Implements sync, query, search, and optional DML operations.
Holds backend URL and auth profile referenced by the connector.
Setup record that ties the Custom Adapter type to the Provider class.
Salesforce objects auto-generated by sync from the backend schema.
- Anything the connector cannot push down to the backend (a filter the API does not support) must be applied on the Apex side. Forgetting this returns wrong results.
- Writes need the External Data Source flagged Writable plus upsertRows and deleteRows implementations. Read-only adapters cannot accept DML.
- External Object queries share governor limits with the calling transaction. A heavy Lightning page that loads three External Objects can exhaust CPU time.
- Schema changes on the backend require a re-sync. Adding a column to the backend without re-syncing leaves the External Object's schema stale.