Development
5 min readIn the world of modern commerce architecture, the debate between monoliths and microservices often boils down to a single trade-off between developer velocity and operational complexity. Microservices offer genuine modularity and scalability but bring a "distributed tax" from network latency, serialization overhead, and propagating security and request context across service boundaries.
Broadleaf's Interlink Client creates an exception to that tax.
When a target service lives in the same JVM as the caller, the Client bypasses the network and invokes the controller method directly: No serialization, no latency, no extra context management. But when the target doesn't, the call goes out over HTTPS without intervention. The caller doesn’t need to know which JVM they or the target is in—the Client already does.
In a traditional microservices environment, every inter-service call looks like this:
A checkout flow that fans out to Catalog, Offer, Cart, and Fulfillment can pay this overhead four times per request. In a FlexPackage deployment, where those services share a JVM, none of that overhead buys you isolation.
The Broadleaf Interlink Client uses Spring WebFlux's WebClient. For remote services it behaves like any other WebClient, using REST over HTTP. However, for services it can resolve in the local JVM, it skips the HTTP path entirely, using what we call Loopback Optimization.
At startup, Interlink inspects the application context for InterlinkReflectionInfo beans matching the requested logical service. If it finds one, it dispatches the call reflectively against the in-JVM controller. This means:
If the service is not local, Interlink falls back to a standard WebClient call over HTTPS. The calling code remains identical.
Tenant IDs, sandbox IDs, and localization settings ride along with every call. Interlink handles this for you.
Interlink uses a single InterlinkRequest type for every call, so you don't need a generated client interface per endpoint. This model abstracts away the differences between a network call and a local method invocation.
InterlinkRequest request = new InterlinkRequest("readProduct")
.withRequestMethod(HttpMethod.GET)
.withUri("https://catalog/products/{id}")
.withArguments(List.of(
new UrlArgument("id", "123"), // For the remote URI template
new MethodArgument(0, "123") // For the local method's first parameter
));
// Interlink decides: Is catalog-service local?
// If yes -> Reflection call. If no -> WebClient call.
String responseJson = interlinkClient.invoke(request);
To enable this optimization, you simply provide InterlinkReflectionInfo beans. These beans tell the client which controller methods map to which logical service names.
@Bean
public InterlinkReflectionInfo productReflection() {
return new InterlinkReflectionInfo(
"readProduct",
"com.broadleafcommerce.catalog.web.endpoint.ProductEndpoint",
"readProductById",
List.of("java.lang.String", "com.broadleafcommerce.data.tracking.core.context.ContextInfo")
);
}
While reflection is powerful, it can be fragile. If a developer changes a controller method signature without updating the corresponding InterlinkReflectionInfo, the loopback will fail at runtime.
To mitigate this, Broadleaf recommends three key strategies:
Broadleaf is rolling the Interlink pattern out across the framework. Not every WebClient has been converted yet, but you can see it in action today in places like the Search Service, where it cuts latency during product indexing, and in several large-scale client deployments where performance was a hard requirement.
The Interlink Client is the backbone of Broadleaf's FlexPackage deployment strategy. It lets you develop and deploy in a "balanced" state, scaling out into full microservices when you need them and retaining the efficiency of a monolith when co-location makes more sense, no more distributed tax.
The result: the same codebase ships as a distributed system in production and as a single process in local development or smaller deployments, with no change to the calling code.
Full documentation lives on the Broadleaf Developer Portal.