The 300 MB default maxmempool Problem

Monday, December 18, 2017

Unconfirmed transactions are quite a hassle for bitcoin users. I recently came across an interesting problem which is not the usual “my transaction is stuck” problem.

In the last weeks of 2017, the number of unconfirmed transactions has again reached all-time highs. Periods with over 100k transactions in my mempool were not unusual. Bitcoin Core limits the system memory allocated for storing unconfirmed transactions to 300 MB by default. This serves as an anti-DoS feature. Fully used 300 MB of RAM equal about 110 MB of actual raw transaction data. This default value can be changed with the -maxmempool <n> option where n is the number of megabytes allocated to store unconfirmed transactions.

 $ bitcoin-cli getmempoolinfo
   "size": 123803,               # amount of tx
   "bytes": 107840125,           # raw tx bytes
   "usage": 298526272,           # tx in ram bytes
   "maxmempool": 300000000,      # maxmempool in bytes
   "mempoolminfee": 0.00016486   # min tx-fee to get accepted

Once 300 MB of system memory is filled, Bitcoin Core starts dropping low-feerate transactions from the mempool for high-feerate transactions. Additionally, a mempoolminfee-threshold is set to prevent new low fee transactions from entering the mempool.

transactions dropping from the mempool

A node operator can increase or decrease the maxmempool option to better fit their system. I assume that for example, some block-explorers have increased their nodes maxmempool. I know that Jochen Hoenicke, for example, has a node running with a maxmempool of 2GB.

The Problem

Small differences in the mempool are common. However, with an increased maxmempool a nodes mempool can differ vastly from a majority of other nodes on the network. These nodes, especially when they power a block-explorer, still many keep unconfirmed transactions the majority of the network has already dropped. This can be irritating for users.

I came across a particular form of this problem, when a friend asked me, why he can see a certain low-fee transaction on, but not on My local node, with a default 300 MB maxmempool, responded with an error on calling the getrawtransaction RPC with the txid.

 $ bitcoin-cli getrawtransaction <txid>
 error code: -5
 error message:
 No such mempool transaction.

However, using the API to query the raw transaction worked fine. I tried rebroadcasting the raw transaction with sendrawtransaction. This failed.

 $ bitcoin-cli sendrawtransaction <rawtx>
 error code: -25
 error message:
 Missing inputs

Looking at the missing input I noticed that it references an unconfirmed change output from a transaction with equally low fees. However, I again wasn’t able to find the parent transaction for the input in my local mempool or on Only had it. And this transaction again referenced an unconfirmed low-fee output as an input.

With the context of the maxmempool-limit this started to make sense.

My take on what happened

My take on what happened is, that has a higher maxmempool-limit than e.g. and therefore does not drop the transactions. A user checking sees the transaction, a user checking doesn’t.

chained mempool transactions

The real issue appears when the original sender is not aware of this and has a peer with a larger-than-default mempool. He unknowingly continues to chain transactions to an unconfirmed parent transaction that the vast majority of the network rejects. The broadcasted transaction spends an output that references a dropped transaction and therefore is invalid.

David Harding pointed out that the sender could use BIP-125 Replace-By-Fee to update an unconfirmed transaction with new outputs:

All text and images in this work are licensed under a Creative Commons Attribution-ShareAlike 4.0 International License Creative Commons License


Image for Plotting the Bitcoin Feerate Distribution

March 18, 2018

Plotting the Bitcoin Feerate Distribution

How did the median Bitcoin feerate evolve from 2013 to 2015? When were the feerate spikes in 2017? Visualizing the Bitcoin feerate distribution per block was on my todo list since I’ve started working on the first version of my project in mid-2017. But acquiring the data …