An External ID in Salesforce is a custom field flagged with the External ID attribute, marking it as a unique identifier for the record in an external system (an ERP, billing platform, customer database, etc.). External ID fields can be referenced in upsert operations to match incoming records to existing Salesforce records without needing the Salesforce Id, and they’re indexed for fast lookups in SOQL.
What “External ID” actually changes about a field
When you check the External ID checkbox during field creation or editing:
- The field becomes indexed by Salesforce, so SOQL filters on this field run fast even on large tables.
- The field can be used as the match key in upsert operations (
Database.upsert(records, externalIdField)). - The field appears in the Side bar search scope automatically.
- The field can also be marked Unique (separately) to enforce no duplicates.
The “External ID” flag itself does not enforce uniqueness — that’s a separate Unique checkbox on the field definition. In integration scenarios you almost always combine both: External ID + Unique + Required.
Which field types support External ID?
Only a specific set of data types can be flagged as External ID:
| Field type | Can be External ID? |
|---|---|
| Text | Yes — most common |
| Number | Yes |
| Yes | |
| Auto Number | Yes |
| Date / Datetime | No |
| Picklist (single or multi) | No |
| Checkbox | No |
| Currency, Percent | No |
| Lookup / Master-Detail / Hierarchy | No |
| Long Text Area / Rich Text / URL / Phone | No |
| Formula | No (formula fields can’t be marked external ID) |
| Geolocation | No |
| Time | No |
In practice, Text is the most common type for external IDs because external systems usually provide string-based identifiers (SAP_Material_Code__c, NetSuite_Customer_Id__c).
Why upsert needs an external ID
upsert is the operation that says “insert if not found, update if found.” Salesforce needs a way to decide which existing record an incoming record matches. By default, it matches on the Salesforce Id — but external systems rarely know Salesforce Ids.
Using an external ID as the match key lets you say: “Find the Contact whose SAP_Contact_Id__c equals the value in this incoming row. If it exists, update it. If not, create a new Contact.” This is the foundation of most Salesforce integrations.
// Apex upsert using an external ID field
Contact c = new Contact(
SAP_Contact_Id__c = 'SAP-00012345',
LastName = 'Reyes',
Email = '[email protected]'
);
upsert c Contact.SAP_Contact_Id__c;
External IDs in relationship loading
A powerful pattern: you can populate a lookup or master-detail field during an import by referencing the parent’s external ID instead of its Salesforce Id.
Example: you’re loading Opportunities and each row references the customer Account by its SAP Customer Code. If Account.SAP_Account_Id__c is marked External ID, you can load the Opportunities with a column like Account:SAP_Account_Id__c and Salesforce resolves the lookup automatically — no two-pass import required.
This works in Data Loader, Workbench, the Bulk API, and Salesforce-to-Salesforce integrations.
Limits to remember
- Each object can have up to 25 External ID fields (limits do shift between releases — confirm the current number on the Salesforce docs for the release you’re testing).
- External ID fields are still subject to the normal custom field limits per object (which depend on edition).
- The case-sensitive option on Text external IDs matters —
SAP-00012345andsap-00012345are different values if case-sensitive is on, identical if off.
Real scenario interviewers love
“You need to nightly sync 50,000 Accounts from your billing system into Salesforce. The billing system uses customer codes like
CUST-A0042. How do you avoid creating duplicates?”
Step-by-step:
- On the
Accountobject create a custom fieldBilling_Customer_Code__c, Text(20), External ID = Yes, Unique = Yes, Case-sensitive = depends on source system. - Configure the integration (Data Loader CLI, REST Bulk API, MuleSoft, etc.) to use upsert with
Billing_Customer_Code__cas the match key. - Map the billing system’s customer code into that field on every incoming row.
- Salesforce matches by code: existing Accounts update; new codes insert. No duplicates, no manual ID handoff.
Common interview follow-ups
- Can the standard
Idfield be the external ID? It already is, in effect —Idis unique and indexed. But “External ID” is a flag for custom fields, marking them as the external system’s primary key for upsert purposes. - Does an external ID have to be unique? Not technically — uniqueness is a separate flag. But almost always you want both.
- Can a formula field be an external ID? No.
- Is the external ID field automatically populated? No — it’s just a field. Your integration code or import file populates it like any other field.
Verified against: Salesforce Help — Create Custom Fields and Apex Developer Guide — Upsert Statement. Last reviewed 2026-05-17.