Salesforce Integration Failures: How I Debugged and Fixed API Callout Issues in Production
Salesforce integrations look simple on paper.
Make a REST call. Send data. Get a response.
In reality, Salesforce integrations fail in silent, unpredictable ways, especially in production:
- Data sync stops without warning
- Callouts fail intermittently
- Authentication suddenly breaks
- Jobs keep retrying but never succeed I recently faced this issue in a live Salesforce org, and the root cause was not one thing—it was a combination of bad assumptions, missing error handling, and weak observability.
This post explains why Salesforce integrations fail, and how to fix them properly, step by step.
The Core Problem
Salesforce integrations with external systems fail mainly because:
- Callout errors are not logged properly
- Authentication tokens expire silently
- Timeout and retry logic is missing
- Errors happen inside async jobs (Batch, Queueable, Future)
- Developers assume APIs behave consistently
Salesforce does not automatically “protect” your integration.
If you don’t handle failures explicitly, they go unnoticed.
Step 1: Confirm the Integration Entry Point
First, identify where the integration is running:
- Trigger-based callout?
- Queueable Apex?
- Batch Apex?
- Scheduled job?
Most failures happen inside asynchronous Apex, not UI-triggered flows.
Example (Queueable integration):
System.enqueueJob(new SyncOrderJob(orderId));
If this job fails, the UI will never show an error.
Step 2: Never Call External APIs Directly From Triggers
This is a very common Salesforce mistake.
Wrong approach
trigger OrderTrigger on Order__c (after insert) {
HttpRequest req = new HttpRequest();
// Callout directly from trigger
}
This causes:
- Callout exceptions
- Governor limit issues
- Unpredictable failures
Correct architecture
Trigger → Queueable → Callout
trigger OrderTrigger on Order__c (after insert) {
System.enqueueJob(new SyncOrderJob(Trigger.new));
}
Step 3: Use Named Credentials (Non-Negotiable)
Hardcoding endpoints or tokens will break in production.
Bad practice
req.setEndpoint('https://api.partner.com/v1/orders');
req.setHeader('Authorization', 'Bearer hardcoded_token');
Correct approach (Named Credential)
Go to Setup → Named Credentials
-
Configure:
- Base URL
- Authentication (OAuth 2.0 / JWT / API Key)
Use it in Apex
req.setEndpoint('callout:Partner_API/orders');
Benefits:
- Automatic token refresh
- Environment-safe
- More secure
Step 4: Always Wrap Callouts in try–catch
This is the main reason Salesforce integrations fail silently.
Common mistake
HttpResponse res = http.send(req);
System.debug(res.getBody());
If it fails → job dies → no visibility.
Production-safe code
try {
Http http = new Http();
HttpResponse res = http.send(req);
if (res.getStatusCode() != 200) {
throw new CalloutException(
'API Error: ' + res.getStatus() + ' - ' + res.getBody()
);
}
} catch (Exception e) {
System.debug('Integration failed: ' + e.getMessage());
}
Step 5: Log Failures (Do Not Rely on Debug Logs)
Debug logs are temporary and unreliable in production.
Create a custom Integration_Log__c object.
public static void logError(String source, String message) {
Integration_Log__c log = new Integration_Log__c(
Source__c = source,
Error_Message__c = message
);
insert log;
}
Use it in catch blocks:
catch (Exception e) {
logError('Order Sync', e.getMessage());
}
Now failures are:
- Persistent
- Reportable
- Auditable
Step 6: Handle Timeouts Explicitly
Salesforce has strict timeout limits.
req.setTimeout(10000); // 10 seconds
If your external API is slow and you don’t set this:
- Salesforce terminates the request
- No clear error is shown
Step 7: Use Queueable Apex for Retries
Salesforce does not auto-retry failed callouts.
Add retry logic manually.
if (retryCount < 3) {
System.enqueueJob(new SyncOrderJob(orderId, retryCount + 1));
}
This alone fixes many “random” integration failures.
Step 8: Check Remote Site Settings (Classic Issue)
If you are not using Named Credentials, your callout will fail silently.
Go to:
Setup → Remote Site Settings
https://api.partner.com
Missing this = guaranteed failure.
Step 9: Test Callouts Properly (Mocking Required)
Salesforce will not allow real callouts in tests.
@isTest
private class OrderSyncTest {
static testMethod void testCallout() {
Test.setMock(HttpCalloutMock.class, new MockResponse());
Test.startTest();
System.enqueueJob(new SyncOrderJob(orderId));
Test.stopTest();
}
}
Without mocks:
- Tests fail
- Deployment blocked
Step 10: Monitor Async Jobs Regularly
Go to:
Setup → Apex Jobs
Look for:
- Failed Queueables
- Aborted Batch jobs
- Long-running executions Most integration failures show up here first.
Key Takeaways
Salesforce integrations don’t fail because Salesforce is weak.
They fail because developers trust external systems too much.
To make integrations production-safe:
- Always use Named Credentials
- Never call APIs from triggers
- Log every failure
- Handle retries explicitly
- Treat async jobs as first-class systems
Once these practices are in place, Salesforce integrations become stable, observable, and predictable.
Top comments (0)