Notable changes since the last scalability testing round:
And it's time for the traditional scalability check-up, like in 2025, and in 2024. As usual, the portfolio test was used (996 ARK-inspired stock portfolios with 14,683,696 transactions and 713,800 end-of-month holding records).
| Deployment flavor | AWS instance | 4 Cassandra nodes | 8 Cassandra nodes | 16 Cassandra nodes | 32 Cassandra nodes | Cassandra | Daemon | Bastion/RabbitMQ/Prometheus | Total cores | Hourly cost | Total cores | Hourly cost | Total cores | Hourly cost | Total cores | Hourly cost |
|---|---|---|---|---|---|---|---|---|---|---|---|
| aws.arm64.c7g.8 | c7gd.2xlarge | c7g.large | c7g.large | 42 | $1.8141 | 82 | $3.5557 | 162 | $7.0389 | 322 | $14.0053 |
| aws.arm64.c7g.16 | c7gd.4xlarge | c7g.xlarge | c7g.large | 82 | $3.5557 | 162 | $7.0389 | 322 | $14.0053 | ||
| aws.arm64.c7g.32 | c7gd.8xlarge | c7g.2xlarge | c7g.large | 162 | $7.0385 | 322 | $14.0045 | ||||
| aws.arm64.c7g.64 | c7gd.16xlarge | c7g.4xlarge | c7g.large | 322 | $14.0045 |
| Deployment flavor | Cassandra node cores | Cassandra nodes | Run time, s | Cost of run |
|---|---|---|---|---|
| aws.arm64.c7g.8 | 8 | 4 | 903 | $0.46 |
| 8 | 497 | $0.49 | ||
| 16 | 298 | $0.58 | ||
| 32 | 182 | $0.71 | ||
| aws.arm64.c7g.16 | 16 | 4 | 441 | $0.44 |
| 8 | 248 | $0.48 | ||
| 16 | 160 | $0.62 | ||
| aws.arm64.c7g.32 | 32 | 4 | 259 | $0.51 |
| 8 | 144 | $0.56 | ||
| aws.arm64.c7g.64 | 64 | 4 | 151 | $0.59 |
As usual: colors (green, orange, red, black) - to scale up, number of Cassandra nodes (4, 8, 16, 32) - to scale out.
While overall performance numbers show some improvement (probably, thanks to the Cassandra LWT-related changes), scalability patterns remain largely unchanged.
Some considerations when choosing a message queue engine for Capillaries.
This is what we want, ideally. Unfortunately, exactly-once delivery is not a solved problem in the general case, and components that perform actual data processing must be prepared to handle duplicate deliveries and processing component crashes. Minimizing those cases is a good enough goal.
This one is easy - no real-time updates are required. Just make sure data processing components do not sit idle for too long. Capillaries is all about efficient resource utilization.
To minimize vendor lock-in, support a protocol rather than a specific message broker.
Capillaries does not pass processed data through the message broker. Messages are therefore almost guaranteed to be smaller than 2 KB.
A Capillaries data processing node can be split into 100, 1000, or even more batches. A useful Capillaries run will rarely contain more than 20 nodes. A powerful Capillaries deployment could probably handle 100 runs simultaneously.
Each batch requires exactly one message, which means the system may contain up to:
1,000 x 20 x 100 = 2,000,000
messages at any given moment.
Capillaries assumes retries are essential. Common scenarios include failed data processing components or messages delivered when a node is not yet ready to be processed because its dependency nodes have not completed.
Retry delays must be configurable either globally in the message broker or individually for each returned message.
Some users cannot afford to re-run part of a Capillaries script simply because the message broker was unavailable for five minutes. Those users are willing to pay for sophisticated clustered broker solutions with strong availability guarantees and a solid reputation.
For on-premises deployments, the message broker should support both amd64 and arm64 Linux environments, whether running in Docker containers or virtual machines.
AMQP 0.9.1 was a solid choice for many years, but the industry appears to be gradually moving toward AMQP 1.0.
The requirements above practically have "AMQP 1.0" written all over them.
An up-to-date list of AMQP brokers is maintained at https://github.com/xinchen10/awesome-amqp.
Among the current leaders are:
On-premises offerings:
Cloud offerings:
Now, with AMQP 1.0 as the protocol of choice, which broker should be used for local development and testing?
As of today, Capillaries has been successfully tested with RabbitMQ 4, ActiveMQ Classic, and ActiveMQ Artemis.
At the moment, ActiveMQ Artemis is the primary choice because it feels like a cleaner, more modern successor to Classic-with less legacy code and a simpler configuration model.
All three options require different server-side configurations for redelivery delays, as well as minor client-side differences (for example, Release vs. Reject semantics).
As for cloud-based production deployments, Capillaries should work with both Amazon MQ flavors. It will not work with Azure Service Bus's AMQP 1.0 implementation until delayed redelivery is supported on the server side.