Maximizing the speed of a MultiChain node and network

The key bottleneck in blockchain performance is the speed at which nodes can process transactions, both when they first arrive (in the memory pool) and when they are confirmed within a block in the chain.

In our tests on high-end hardware, we’ve seen MultiChain nodes process up to 2,500 transactions per second (peak, without confirmation) and up to 2,000 transactions per second (sustained, with confirmation), using the built-in wallet and regular APIs.

In order to optimize MultiChain’s performance, follow the tips below. These relate both to the specifications of the servers on which MultiChain runs, and recommended patterns of usage.

Server specifications

  • Use CPUs with a high clock speed, which provide fast single-threaded performance. Having a large number of CPU cores is less important, since MultiChain can make optimal use of around 4 threads at most.
  • Ensure your CPU frequency scaling governor is set to performance or ondemand (use cpupower utilities on some builds of Linux).
  • If appropriate, use NUMA CPU pinning to maximize the bandwidth between CPU and memory (use numactl on Linux).
  • Ensure that the disk storage for each node’s blockchain directory is local, and avoid using network-attached storage.
  • Use solid state disk drives (SSDs) rather than traditional hard disk drives (HDDs).

MultiChain usage

  • If you are sending transactions using any API except createrawtransaction, keep down the number of unspent transaction outputs (UTXOs) tracked by the wallet. This will grow as addresses in the wallet receive incoming payments, and can be seen in the utxocount field of the response to getwalletinfo. To reduce it, take a look at the autocombine* runtime parameters or use the combineunspent API.
  • If you are using transaction filters in MultiChain 2, the main bottleneck will be callback functions such as getfiltertransaction(). Try to use callbacks sparingly, and consider combining filters together in order to reduce the number of these calls.
  • If your workload involves both sending transactions and querying transactions or streams, separate these functions into two nodes.
  • Run MultiChain with the runtime parameter txindex=0 instead of the default value of 1.
  • Set mining-turnover=1.0 in the blockchain parameters (or use the miningturnover runtime parameter) to minimize the number of forks (although in any event these will be rare).
  • If you are publishing large numbers of stream items, consider publishing multiple items in each transaction, using createrawsendfrom (or publishmulti in MultiChain 2). Using this technique, MultiChain can publish over 10,000 small items per second on high-end hardware.

To push a node even further, consider avoiding using its wallet completely. Only use the address in the wallet for connecting to the network or mining blocks, and perform all other transactions using addresses not in the wallet. Build and sign transactions within your application, using a bitcoin-compatible library or multiple cold nodes running in parallel, and send the signed transactions using the node’s sendrawtransaction API.