The two are both Salesforce-initiated outbound integration patterns, but they differ in whether the caller waits for a response.
Side by side
| Aspect | Request and Reply | Fire and Forget |
|---|---|---|
| Caller waits for response? | Yes | No |
| Synchronous or async? | Synchronous | Asynchronous |
| Used when | Caller needs the answer to proceed | Downstream system just needs to be told |
| Failure handling | Caller sees the error immediately | Caller already moved on; retries happen out-of-band |
| Typical tech | REST/SOAP callout, External Services | Platform Events, @future callout, Outbound Messages |
| Governor pressure | High — counts against sync callout time and transaction CPU | Lower — runs in async context with separate limits |
Request and Reply — example
User clicks “Run Credit Check” on a Lead. The UI waits 1–3 seconds. Salesforce calls the bureau API, receives the score, displays it.
public static Integer fetchCreditScore(String taxId) {
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:Credit_Bureau/score');
req.setMethod('POST');
req.setBody(JSON.serialize(new Map<String, String>{'ssn' => taxId}));
HttpResponse res = new Http().send(req); // BLOCKS here
Map<String, Object> body = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
return (Integer) body.get('score');
}
The caller’s transaction holds open while send() is blocked. If the bureau is slow, the user sees a spinner. If it errors, the user sees the error.
Pick Request-Reply when:
- The caller’s next step depends on the response
- The expected latency is < a few seconds
- The user can reasonably wait
Fire and Forget — example
A new Opportunity is created. ERP needs to know, but the sales rep shouldn’t wait for SAP’s three-second response time.
trigger OpportunityTrigger on Opportunity (after insert) {
List<Opportunity_Created__e> events = new List<Opportunity_Created__e>();
for (Opportunity o : Trigger.new) {
events.add(new Opportunity_Created__e(
Opportunity_Id__c = o.Id,
Amount__c = o.Amount
));
}
EventBus.publish(events);
}
The trigger completes in milliseconds. The Platform Event is delivered to subscribers (including the external ERP listener) asynchronously. The user sees their saved Opportunity instantly.
Pick Fire-and-Forget when:
- The downstream system’s response doesn’t affect the caller’s flow
- Latency or downstream availability shouldn’t impact UX
- You’re integrating with multiple consumers — a single event can fan out
What about errors?
This is where Fire-and-Forget gets interesting. The publishing transaction succeeds even if the subscriber fails. You need a strategy:
- Retries: Apex subscribers can throw
EventBus.RetryableException(up to 9 retries) - Dead-letter queues: failed events should land in a custom object for ops to inspect
- Monitoring: track subscriber lag with the EventBus replay metadata
Hybrid: Async Request-Reply
Sometimes you genuinely need a response, but the round trip is too slow for sync. Pattern:
- Salesforce publishes “credit check requested” Platform Event with a
Correlation_Id__c. - External bureau processes asynchronously.
- External system publishes “credit check completed” event back, carrying the same
Correlation_Id__c. - Salesforce subscriber updates the original record.
Officially this is two Fire-and-Forgets stitched together with a correlation ID. Common in modern event-driven architectures.
Common interview follow-ups
- Can a single integration use both patterns? — Yes. Real systems often do — sync for the user-facing answer, async for the back-office sync.
- Why prefer Platform Events over
@futurefor Fire-and-Forget? — Multiple subscribers, replay, external consumers via Pub/Sub API, retries withEventBus.RetryableException. - What’s the failure mode of Request-Reply if the external system is down? — Caller sees a
CalloutException; the user’s transaction either rolls back or compensates. With Fire-and-Forget, the publisher doesn’t know.
Verified against: Salesforce Integration Patterns and Practices — Overview. Last reviewed 2026-05-17 for Spring ‘26 release.