QuantumNest
Architecture · Integration

REST, Platform Events, or MuleSoft

Most integration failures are decision failures made weeks earlier. Three valid patterns, three different cost curves, and a framework for picking before you write a line.

QuantumNest Engineering21 Aug 20258 min read
Pattern 01

REST callout

synchronous · request-response
~ 200 ms typical
Pattern 02

Platform Events

asynchronous · publish-subscribe
~ 1 to 5 s typical
Pattern 03

MuleSoft

orchestrated · middleware
cost per call adds up

There are three credible ways to connect Salesforce to another system. Synchronous REST callouts, asynchronous Platform Events, and a dedicated middleware layer, which inside the Salesforce ecosystem is almost always MuleSoft. Most integration projects do not fail because the chosen pattern was technically wrong. They fail because the choice was made without anyone naming the trade-offs out loud. The framework below removes the religion from the conversation, and it usually resolves the decision in half an hour.

01.Start with three questions

Before opening an editor, write honest answers to three questions. Does the caller need an answer in order to continue? If a user is staring at a screen waiting, yes; if a background process is firing a notification, no. What is the cost of a failed call? A missed payment is high; a missed analytics ping is low. And how many systems consume this data? One target is one thing; five targets with different shapes is another entirely. The combination almost always points at one pattern without further debate.

02.When REST is right

Synchronous REST is correct when the caller needs an answer, the volume is moderate, and the endpoint is reliable. A button on the opportunity that fetches a credit score is the canonical case: click, wait two hundred milliseconds, render the answer. The strengths are simplicity and immediacy. The weaknesses are coupling and concurrency, because if the endpoint is slow your transaction is slow, and if it is down your user gets an error. We default to REST when volume stays under about a thousand calls an hour, the response is needed in real time, and the failure domain is contained.

CreditServiceCallout.cls
// Synchronous: the user is waiting, so we block and return a result.
public static Decimal fetchScore(Id accountId) {
  HttpRequest req = new HttpRequest();
  req.setEndpoint('callout:CreditApi/score/' + accountId);
  req.setMethod('GET');
  req.setTimeout(10000);
  HttpResponse res = new Http().send(req);
  if (res.getStatusCode() != 200) {
    throw new CalloutException('Credit API returned ' + res.getStatusCode());
  }
  return (Decimal) JSON.deserializeUntyped(res.getBody()).get('score');
}

// REST: one endpoint, one answer, the caller blocks. Note the explicit timeout and status check.

03.When Platform Events earn their complexity

Platform Events are correct when the caller does not need an answer, when the data is interesting to more than one consumer, or when consumption is decoupled in time from production. The canonical case is a record changing in Salesforce that three downstream systems want to know about. Without events you would write three outbound callouts in a trigger, with all the coupling that implies. With events you publish once, and each system subscribes independently. The trade-off is latency and certainty: delivery is at-least-once, so subscribers must be idempotent, and there is a small delay between publish and subscribe. Both are usually fine, occasionally deal-breakers.

OrderEventPublisher.cls
// Asynchronous: publish once, any number of systems subscribe.
Order_Shipped__e evt = new Order_Shipped__e(
  Order_Id__c = order.Id,
  Tracking__c = order.Tracking_Number__c,
  Shipped_At__c = System.now()
);
Database.SaveResult sr = EventBus.publish(evt);
if (!sr.isSuccess()) {
  // Log, do not block. The event bus handles retry.
  Logger.error('Publish failed', sr.getErrors());
}

// Platform Events: the publisher does not know or care who is listening. Coupling drops to near zero.

The pattern that ships fastest is usually REST. The one that scales longest is usually Platform Events. The one that needs the most discipline is usually MuleSoft.

04.When MuleSoft is the right call

MuleSoft is correct when the integration does more than move data: when there are transformations to apply, multiple sources to combine, retries with backoff that should not live inside Salesforce, or governance that demands a dedicated layer. A customer record that exists in Salesforce, an ERP, a marketing platform, and a billing system, all needing to stay in sync, is the textbook case. You can do this in raw Apex callouts. Doing it well is hard, and MuleSoft makes it tractable. The cost is real, both licensing and the need for Mule expertise, but a well-instrumented flow with clear logs is far faster to debug than a clever callout chain, and the licence pays back as the integration surface grows.

05.The decision, as a tree

Caller needs ananswer now? YES NO Many systems, heavytransformation? YES NO One subscriber, simplepush? YES NO MuleSoft REST callout Outbound Msg /Change Data Capture Platform Events four questions, four destinations
// the decision resolves in three or four questions. the escape hatches at the bottom cover the narrow cases.

06.Costs to be honest about

REST has near-zero infrastructure cost but a high cost per integration when you have many of them. Platform Events carry a per-event cost against your edition's allocation. MuleSoft carries both licensing and runtime cost. The cost most teams underestimate, though, is the operational one: debugging. A clear MuleSoft flow with proper logs is cheaper to maintain over years than a clever Apex chain that only its author understands.

The honest test

If you cannot describe an integration's failure mode in one sentence, the design is not finished. "It calls a REST endpoint and shows the user an error if it fails" is finished. "It uses MuleSoft" is not.

07.Mixed patterns are the norm

A mature org does not pick one pattern; it picks the right one per integration. The typical shape is a handful of REST callouts for real-time user actions, a steady flow of Platform Events for system-to-system propagation, and MuleSoft for the half-dozen genuinely complex enterprise integrations. Three more options exist for the narrow cases: Outbound Messages for very simple async push to a single endpoint, Change Data Capture for replicating Salesforce changes outward without trigger code, and Heroku Connect when the consumer wants SQL access to a mirror. Each is correct in a narrow situation and none is a default. Start with the three primary patterns, reach for the escape hatches only when their specific strength matches what you actually need, and the integration layer stays something the next engineer can reason about.

Building a new integration?

We design integration architectures grounded in the real constraints: latency, volume, and the cost of failure. Send us the use case and we will give you our honest recommendation.

Talk to an architect