New JSON-RPC API mega Q&A

I’d like to write small EDIT: not small clarifications about the design and behavior of chainHead_follow, because I see a lot of confusion about this function. I’m not sure if the forum is the most appropriate place for this, but I can link to this post from other places later.


In order to understand chainHead_follow, it is important to understand that the JSON-RPC server you are connected is one member of the peer-to-peer network of the blockchain, and that all members of the peer-to-peer network are equal. Contrary to traditional client-server architectures, there’s no “master” that always determines the truth.

Consequently, there is no objective concept of “head of the chain”. The JSON-RPC server you are connected to thinks that the head of the chain is a certain block, while other nodes might think that the head of the chain is at a different block, and they are both equally correct.

What calling chainHead_follow does is yield the head of the chain according to the node you are currently connected to. Many people seem to expect that this function yields “the” head of the chain. But the concept of “the” head of the chain doesn’t make sense in a blockchain. Each node has their own head of the chain.

It is important to know that a node can absolutely not guarantee that it has downloaded all the blocks that it could potentially download, and can absolutely not guarantee that it is missing blocks.

For example, if Alice is at block 100 and Bob is at block 99, it is in no way guaranteed that Bob is missing one block, because it might be that Alice’s block 100 is actually invalid. The only way for Bob to know whether it could import Alice’s block 100 is to download that block and verify it, but if it does that then it can also instantaneously update its head of the chain.

In other words, as soon as a node knows that it can advance its head of the chain, it instantaneously does so. There is no period of time during which a node knows that it can potentially advance its head of the chain but hasn’t done so yet.

In the legacy JSON-RPC API, the system_health returns a isSyncing boolean which indicates whether the node is in the process of downloading blocks.
However, as I’ve just explained, a value of isSyncing equal to true is in no way a guarantee that the node is actually syncing. The syncing might stop at any moment, even if isSyncing is true.

The value of isSyncing is currently used by PolkadotJS in order to determine whether blocks are arriving at a reasonable rate (if isSyncing is false, blocks are expected to arrive roughly every 6 seconds) or at an unreasonable rate (if isSyncing is true, blocks are being downloaded very quickly), which is useful for UI purposes.
However, now that all node implementations support warp syncing, this is no longer accurate. Blocks always arrive at a reasonable rate.

For these two reasons, this boolean is not present in the new JSON-RPC API.


I have noticed that some developers try to connect to a JSON-RPC server, then wait for this JSON-RPC server to reach the head of the chain, then only start displaying data.

As explained in the previous section, the second step (waiting for the JSON-RPC server to reach the head of the chain) is non-sensical. The JSON-RPC server is always at the head of the chain. It is fundamentally not possible for the JSON-RPC server to indicate whether it is going to yield more blocks any time soon.

Instead of indicating whether the JSON-RPC server is at the head of the chain (which, again, is non-sensical), what you want to do instead is indicate whether the head of the chain of the JSON-RPC server is far away in the past. To do so, you can use the timestamp at which the block has been authored and that can be found in the state.

No matter what chainHead_follow yields, accept that this is the head of the chain and try to display it in the UI.

Keep in mind that even if the block at the head of the chain is old, it is not a guarantee that newer blocks exist, as it might simply be that Internet connectivity is broken, or that the chain might be halted due to a technical issue or, in the case of on-demand parachains, intentionally.


When it comes to light clients, in practice, if the head of the chain is old, its storage will be inaccessible. JSON-RPC requests that query the storage of the head of the chain will return errors.

It is, however, important to understand that the storage of the head of the chain might be inaccessible no matter what. Just because the head of the chain is recent doesn’t mean that it will be accessible.

The head of the chain being inaccessible shouldn’t be seen as a problem whose solution is to wait for the head of the chain to update to something more recent.

As explained above, if you are writing a UI, you should try to display the head of the chain no matter what. If the storage is inaccessible, then show placeholders in the UI, as you would if Internet connectivity was broken (after all, broken Internet connectivity is one of the reasons why it might be inaccessible).


I think that most of the misunderstandings concerning chainHead_follow come from the fact that blockchains are so different from traditional client-server architectures.

In most situations, a light client behaves similarly to a client in a client-server architecture. But if things go a little bit wrong (Internet connectivity lost, consensus issue, chain halted, etc.), a properly-written UI will continue to work, while a poorly-written UI will not.

The reason why blockchains exist is to be a platform for strong, censorship-resistant, always-accessible, applications. Let’s not make UIs be the weak link that breaks at the first sign of a problem that blockchains are expected to be robust against.

Thank you for reading and feel free to ask questions.