MuleSoft's Scatter-Gather router is a powerful integration pattern that allows you to send a single message to multiple routes simultaneously and then aggregate their responses. It's commonly used when parallel processing is needed, such as calling multiple external APIs at the same time.
In real-world integrations, Scatter-Gather is useful for reducing latency by parallelizing service calls. For example, a retail system may fetch inventory status from multiple warehouses concurrently and aggregate the results to provide a unified response.
Scatter-Gather supports various aggregation strategies, including default, custom, or using DataWeave transformations. Understanding how to manage response collection and potential timeouts is crucial to avoid incomplete data or bottlenecks in production environments.
Error handling is an important consideration with Scatter-Gather. Each route may succeed or fail independently, so implementing error propagation, retries, and fallback mechanisms ensures robustness in your integrations.
Performance tuning involves balancing parallelism, memory consumption, and processing time. Optimizing the number of concurrent routes and leveraging asynchronous flows can improve throughput while maintaining reliability.
The Scatter-Gather router in MuleSoft is used to send a message to multiple routes concurrently and then collect their responses into a single message. This allows for parallel processing of multiple tasks, reducing overall execution time.
A practical use case would be a financial application that needs to fetch exchange rates from several external services simultaneously. Using Scatter-Gather, the application can query all services in parallel and aggregate the results to determine the most accurate rate efficiently.
Each route within a Scatter-Gather flow operates independently, so errors in one route do not automatically fail the others. By default, MuleSoft aggregates the successful responses and can include error details for failed routes.
Best practices include implementing on-error-continue or on-error-propagate scopes for each route, setting appropriate timeouts, and using fallback responses. This ensures the integration remains resilient, provides meaningful error feedback, and avoids partial data issues.
Aggregation strategies determine how responses from multiple routes are combined. MuleSoft provides a default strategy that aggregates responses into an array, but this may not always meet business requirements.
Custom aggregation is useful when responses need to be merged into a structured object, filtered, or transformed using specific logic. For instance, combining inventory counts from different warehouses into a single summarized JSON object would require a custom aggregation using DataWeave.
Scatter-Gather executes multiple routes in parallel, not sequentially. Aggregation of responses can be customized using DataWeave or custom logic.
Automatic indefinite retries are not a feature; retries must be explicitly configured using error handling mechanisms.
Timeouts prevent one slow route from blocking the entire flow. Custom aggregation ensures responses are structured correctly, and error handling allows graceful handling of failed routes.
Blindly increasing parallel threads without limits can lead to resource exhaustion, so it is not a best practice.
Scatter-Gather is designed for parallel execution and response aggregation. Sequential operations on a single resource are better handled with other patterns like Choice Router or Flow.
This configuration shows a basic Scatter-Gather that references two flows. Each flow can contain an HTTP request to a different endpoint.
Responses from both flows will be aggregated into an array and passed downstream for further processing.
// XML
<scatter-gather doc:name="Scatter-Gather">
<flow-ref name="Call-Endpoint-1" />
<flow-ref name="Call-Endpoint-2" />
</scatter-gather>
Scatter-Gather responses are returned as an array. DataWeave can map each element to a named field in a JSON object.
This approach improves readability and allows downstream systems to access responses by descriptive keys.
// DataWeave
%dw 2.0
output application/json
---
{
endpoint1Response: payload[0],
endpoint2Response: payload[1]
}
The on-error-continue scope ensures that even if Route1 fails, Route2 continues execution.
Errors are logged for monitoring and troubleshooting without interrupting the overall flow.
// XML
<scatter-gather doc:name="Scatter-Gather">
<flow-ref name="Route1" />
<flow-ref name="Route2" />
</scatter-gather>
<on-error-continue logException="true" doc:name="Handle Errors" />
This flow executes two routes in parallel and aggregates the results into a structured JSON object using DataWeave.
By explicitly mapping each response to a key, the downstream processing can easily consume named elements rather than array indexes.
// XML
<scatter-gather doc:name="Scatter-Gather">
<flow-ref name="Fetch-User" />
<flow-ref name="Fetch-Orders" />
</scatter-gather>
<transform doc:name="Aggregate Responses">
<dw:transform-message>
<dw:set-payload><![CDATA[%dw 2.0
output application/json
---
{
user: payload[0],
orders: payload[1]
}]]></dw:set-payload>
</dw:transform-message>
</transform>
Scatter-Gather improves response time through parallel execution, but under heavy traffic it can become a bottleneck because each route consumes threads, memory, and connection pool resources simultaneously. If multiple APIs are slow or return large payloads, the Mule runtime may experience thread starvation or increased garbage collection activity.
Optimization starts with limiting unnecessary parallelism. Only independent operations should be executed concurrently. Connection pools, HTTP requester configurations, and timeout values should be tuned carefully. In large enterprise integrations, teams often externalize slow operations into asynchronous flows or queues instead of executing everything inside a single Scatter-Gather block.
Monitoring is equally important. Metrics such as average route latency, memory utilization, and thread pool saturation help identify which downstream systems are causing delays. Many production issues blamed on Mule are actually caused by poorly behaving backend services.
Before entering a Scatter-Gather component, the payload usually contains a single message object that all routes can access independently. Each route receives a copy of the same Mule event unless explicitly transformed within the route.
After execution, MuleSoft aggregates all route outputs into a collection structure. In Mule 4, the payload becomes an object where each route result is stored using route indexes or route names. Developers often use DataWeave immediately after aggregation because downstream systems rarely consume the default structure directly.
Understanding this transformation is important during debugging. Teams frequently encounter issues where downstream components fail because they expect a flat payload while receiving an aggregated object instead.
Scatter-Gather works best for independent operations that can safely execute in parallel. Backend API rate limits are important because simultaneous requests may exceed allowed thresholds.
Payload size also matters because aggregated responses can significantly increase memory usage. Database normalization rules are unrelated to Scatter-Gather routing behavior.
Timeout handling is critical because one delayed route can affect the entire response aggregation. Teams often configure route-level error handling to avoid complete flow failures.
Timeouts directly affect thread utilization because blocked threads remain occupied while waiting for responses. Infinite retries are not automatically configured by MuleSoft.
Scatter-Gather is commonly used when multiple systems must be queried simultaneously to reduce overall latency. Customer profiles, shipment tracking, and pricing systems are common enterprise examples.
Sequential validations are not ideal candidates because they typically depend on previous execution results.
This example demonstrates parallel API invocation using three routes. Each route executes independently, reducing the total wait time compared to sequential execution.
Logging the aggregated payload is useful during testing and troubleshooting because developers can inspect the exact structure returned after aggregation.
// XML
<flow name="parallel-api-flow">
<scatter-gather doc:name="Scatter-Gather">
<route>
<http:request method="GET" path="/customer" config-ref="HTTP_Config" />
</route>
<route>
<http:request method="GET" path="/orders" config-ref="HTTP_Config" />
</route>
<route>
<http:request method="GET" path="/payments" config-ref="HTTP_Config" />
</route>
</scatter-gather>
<logger level="INFO" message="#[(payload)]" />
</flow>
In enterprise integrations, not every route failure should terminate processing. This transformation removes failed route responses and keeps only successful results.
This pattern is especially useful in reporting systems where partial results are acceptable and business users prefer degraded responses over total failures.
// DataWeave
%dw 2.0
output application/json
---
payload filterObject ((value, key) -> !(value is Error))
Different downstream systems often have different SLA expectations. This example demonstrates assigning separate timeout values for independent APIs.
Using aggressive timeout values prevents slow systems from blocking overall transaction processing for extended periods.
// XML
<scatter-gather>
<route>
<http:request method="GET"
path="/inventory"
responseTimeout="5000"
config-ref="HTTP_Config" />
</route>
<route>
<http:request method="GET"
path="/pricing"
responseTimeout="3000"
config-ref="HTTP_Config" />
</route>
</scatter-gather>
Transforming responses inside each route keeps aggregation cleaner and reduces downstream transformation complexity.
This approach is commonly used when integrating legacy APIs that return inconsistent payload structures.
// XML
<scatter-gather>
<route>
<http:request method="GET" path="/customer" config-ref="HTTP_Config" />
<transform>
<dw:transform-message>
<dw:set-payload><![CDATA[%dw 2.0
output application/json
---
{
customerId: payload.id,
customerName: payload.name
}]]></dw:set-payload>
</dw:transform-message>
</transform>
</route>
<route>
<http:request method="GET" path="/orders" config-ref="HTTP_Config" />
<transform>
<dw:transform-message>
<dw:set-payload><![CDATA[%dw 2.0
output application/json
---
{
totalOrders: sizeOf(payload)
}]]></dw:set-payload>
</dw:transform-message>
</transform>
</route>
</scatter-gather>
Flattening aggregated responses makes APIs easier for frontend and consumer systems to use because consumers no longer need to understand internal route structures.
This pattern is frequently implemented in experience APIs where response simplicity directly impacts frontend development speed.
// DataWeave
%dw 2.0
output application/json
---
{
customer: payload.route0.customerName,
orderCount: payload.route1.totalOrders,
paymentStatus: payload.route2.status
}
Scatter-Gather can be integrated with asynchronous flows to allow long-running or independent processes to execute in parallel without blocking the main transaction. Asynchronous execution prevents slow external systems from impacting the overall response time.
It is preferred over synchronous execution when multiple API calls or processing tasks do not depend on each other and need to maximize throughput. For example, retrieving user activity logs and recommendations concurrently allows the system to return results faster to the client.
Since each route in Scatter-Gather may return different response formats (JSON, XML, plain text), DataWeave transforms are used to normalize the responses into a unified structure.
Standardizing responses enables easier aggregation and downstream processing. For example, API responses from different third-party services can be converted into a common JSON object with consistent field names before aggregation.
On-Error-Continue helps handle route-specific errors gracefully, while DataWeave is used to transform and aggregate responses.
Choice Router and Scheduler are unrelated to Scatter-Gather's parallel routing functionality.
Scatter-Gather executes multiple routes in parallel, which consumes threads and memory. Large aggregated payloads can cause memory pressure.
Deadlocks are not typical in Scatter-Gather since routes are independent, but error handling must be carefully implemented to avoid incomplete results.
Each route executes independently, logging its response immediately. This is useful for debugging and monitoring individual service performance.
Aggregated payloads are still available downstream if further processing is required.
// XML
<scatter-gather doc:name="Product Fetch">
<route>
<http:request method="GET" path="/productA" config-ref="HTTP_Config" />
<logger level="INFO" message="#['Product A: ' ++ payload]" />
</route>
<route>
<http:request method="GET" path="/productB" config-ref="HTTP_Config" />
<logger level="INFO" message="#['Product B: ' ++ payload]" />
</route>
</scatter-gather>
This transformation ensures that only successful route responses are included in the final aggregated payload.
This pattern improves resilience and allows downstream consumers to rely only on valid data.
// DataWeave
%dw 2.0
output application/json
---
payload filter ((item) -> item.status == "success") map ((item) -> item.data)
Scatter-Gather is not ideal for sequential processes where each step depends on the previous one. For instance, updating inventory after payment confirmation must be sequential to maintain data integrity.
Using Scatter-Gather in such a scenario could lead to race conditions, inconsistent states, or data conflicts because independent parallel execution does not enforce order.
Limiting parallelism prevents thread exhaustion, asynchronous flows reduce blocking, and optimizing payload size reduces memory usage.
Using blocking flows for all routes can reduce scalability and is generally not recommended.
The on-error-continue ensures that if the primary API fails, the route sets a fallback response without impacting the other route.
This approach helps maintain partial functionality in production.
// XML
<scatter-gather>
<route>
<http:request method="GET" path="/primaryAPI" config-ref="HTTP_Config" />
<on-error-continue>
<logger message="Primary API failed, using fallback" level="WARN" />
<set-payload value="Fallback Response" />
</on-error-continue>
</route>
<route>
<http:request method="GET" path="/secondaryAPI" config-ref="HTTP_Config" />
</route>
</scatter-gather>
Monitoring Scatter-Gather performance involves tracking metrics such as route latency, response times, memory usage, and thread pool saturation. Using MuleSoft Anypoint Monitoring or external APM tools allows teams to visualize bottlenecks and slow routes.
Logging aggregated payload sizes and per-route execution time helps identify problematic APIs. Combining this data with error logs enables proactive tuning, such as adjusting timeouts, limiting parallelism, or moving long-running operations to asynchronous flows.
In high-throughput systems, automated alerts based on SLA thresholds are critical. Teams often set up notifications if any route exceeds expected execution time, helping maintain system reliability and user satisfaction.