Measure before you tune
The instinct when an ESB slows is to add consumers. In roughly half of the estates we assess, that makes things worse — more consumers contending for the same downstream connection pool increases lock contention and tail latency without improving throughput.
Start with four signals per hop: arrival rate, service time distribution, queue depth over time, and error-and-retry rate. Together these identify whether the constraint is capacity, contention, or a retry storm masquerading as load.
The usual suspects
Transformation cost is the most commonly underestimated. XSLT or DataWeave transformations over large payloads consume far more CPU than teams expect, and they are frequently executed multiple times along a single message path because each hop re-parses the payload.
Persistence configuration is the second. Fully persistent, synchronously acknowledged queues are correct for financial messages and wasteful for telemetry. Applying one durability policy to every channel guarantees the estate runs at the cost profile of its strictest message class.
The third is downstream blocking. An ESB is rarely the true bottleneck; it is usually the component that makes a slow downstream system visible.
Structural remedies
Batch small messages where ordering permits, and split large ones where it does not. Introduce claim-check patterns so bulk payloads travel through object storage rather than the message bus. Separate channels by durability class so high-volume, low-value traffic does not pay for exactly-once guarantees it does not need.
Where ordering constraints force serialisation, partition by a business key so that ordering is preserved within a partition while parallelism is preserved across partitions. This single change frequently doubles achievable throughput on clearing-style workloads.
Proving the fix holds
Every remediation should be validated against a reproducible load profile derived from production traffic, including its burst shape. Average-rate testing hides the failure mode that matters, because queues fail at peaks, not at means.
Establish service-level objectives on end-to-end latency percentiles rather than component averages, and alert on queue-depth trend rather than absolute threshold. Trend alerting gives operators time to act; threshold alerting tells them they are already late.
