Please excuse my lack of knowledge on some aspects of how Ethereum works.

I'm creating a DAPP that uses web3 to communicate with the blockchain. I have the need to receive events from a certain contract as soon as they happen. What is the best method to use? Specifically, what is the most reliable method that can handle the event as close to the time it was sent as possible.

I've been using Infura nodes so far but they do not support event calls. My alternative now is to run a local ethereum node (geth). Will this be the optimal approach in terms of receiving events quickly?

What are the important considerations that would come in to play here? does network speed, number of peers etc. have a great a effect?


This answer only partly addresses your question.

Your logical position in the Ethereum network (i.e., which peers you have) will affect what you see as being the canonical chain at any given point. Due to the possibility of temporary forking, if you react immediately to a block, you should be ready to handle the block becoming "undone" if it is part of a losing fork.

Depending on your application, you may also wish to run many independent nodes and have your software capable of becoming eventually consistent so that you can be on multiple forks at the same time; this allows you to react faster to changes, regardless of which fork you hit. The chain considered canonical (for any instant) depends on which blocks you receive first. This means that not only do your peers matter (because different peers will see different chains as being canonical) but also your latency to the peers will affect which node geth believes to be canonical. With only a few peers, bandwidth is less important than your latency/OS' ability to handle packets (1). Thus, you will only see one version of the blockchain with a single geth instance when, in fact, there might be multiple versions at any given instant. As a result, you might actually run a few blocks "slow" relative to the winning chain if you only used one instance. For example, if you are on chain A at block x which contains transaction a and you react to it and then chain B wins at block x + 1 and it contains transaction b (also at block x), then you will be one block late at handling the transaction. In fact, because more peers will have a non-zero impact on the performance of your node, if your goal is the fastest reaction time, it may actually be preferable to run more physical nodes with fewer peers each. On the other hand, if your goal is to propagate something out quickly, having many peers per node is probably helpful.

Thus, multiple nodes allow you to react to different versions of the blockchain as they appear. The likelihood of forking decreases with slower block times, but is still non-zero.

In addition to the time to receive a block, if you want to react as quickly as possible, you also need to process the new block; this means a fast CPU, probably with AES acceleration, and as fast a storage volume as you can include. I'm guessing lots of RAM for caching won't hurt either, based on a strategy for mitigating the effects of the attack that necessitated EIP150. The CPU speed and storage speed definitely matter for Parity (as reported by Parity's log output) and RAM starvation has negative effects. I couldn't tell you whether a high core count is preferable to a higher single threaded execution frequency, though. Maybe I'll post that as a question here, but it is possibly dependent on things like the contents of the incoming blocks.

(1) At 100KiB/block, transmitting a block on a relatively modest 100Mbps pipe takes 8ms (give or take). This is about the same amount of time as it takes a packet to travel the short distance of London to Paris with a direct route.


Infura nodes do support event calls; There are some limitations and performance issues when trying to get logs from the past over a wide range, but if you're just listening to events from a particular contract that should work fine. See this example for how you would do this using Web3 + JavaScript. There are also python libraries with similar functionality.

If you don't want to be dependent on Infura you may prefer to run your own node. It may also be useful to do this in parallel with Infura, so your service still runs if one or the other falls over. The same logic points towards running both a Geth and a Parity node.

In theory blocks will show up slightly faster in places with less latency to the servers they were mined on. So if you really want to get the blocks fastest, you might benefit from having nodes spread around the world. If possible you want to peer directly with the bigger miners, but I'm not sure how you'd find and connect to their nodes.

You should also get events faster if your node can validate them faster, which implies good CPU and I/O, but YMMV; It may be worth trying VMs of varying specs and measuring whether it makes any detectable difference.

Finally, be aware that if you're making a DApp, the usual assumption is that the client connects to a node directly without going through any other party. If they're using MetaMask, this will default to Infura, but the user could substitute their local node. Following this pattern you wouldn't normally even control which node they connect to, although you could make a node available for your users yourself and hard-code it in your DApp.

  • Just tried events again and it's working perfectly fine. Had read somewhere that it wasn't possible.
    – monokh
    Sep 26 '17 at 12:05
  • I think watching for stuff happening in new blocks has always worked, but they didn't used to support getting data from past logs. Sep 26 '17 at 23:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.