ESP8266 HTTP vs MQTT Servers


The ability to communicate with your IoT things — to send commands and receive responses is an essential pillar of your “connected” system. You need a network link to control things and to read sensors. Two of the most common Internet to machine communication protocols used with the ESP8266 and other MCUs are http and MQTT.

There are advantages and drawbacks using either one of these methods.

So which one is better?

For an assessment, I created a simple Arduino IDE sketch with just two metrics in mind for the evaluation. First was the simplicity of the application code. How clean was the framework needed to implement the server?

The other concern was latency. That is, how long  is required from the time of a client request to server reply? I was curious to measure this time. Is the delay magnitude in the order of milliseconds, or seconds?

The Sketch

I started out with the intent on creating two sketches; one of an http server and one for MQTT. But what became apparent was that other than the code needed to connect, read and write to the protocol, the software was almost identical. So for simplicity and efficiency, the http and MQTT servers were combined into a single sketch.

This also made the evaluation easier-there was no need to reload the firmware to switch protocols.

The typical Arduino IDE based http server requires the use of two class objects. These objects are defined in WiFi.h for Arduino based systems and the ESP8266WiFi.h library for the ESP8266.

  • WiFiServer
  • WiFiClient

The major shortcoming with the Arduino IDE library is the need in the user sketch to poll for new connections in the loop(). It would be far more efficient to register a callback function that is executed upon an external client connection. Like the EspressIf SDK Iot_demo example web server.

This constraint alone would be sufficient justification to use the Espressif SDK over the Arduino IDE for all but the simplest Web Server application.

Fortunately, however, there is a way to use the SDK callbacks with the Arduino IDE. Here is how it is done. That is just what we will use for comparing the http and MQTT servers. The sketch for this test is just a reuse of that sketch with the added code needed to support MQTT. The Dual MQTT & HTTP Web Server code is here.

Code Assessment

When looking at the code structure for the MQTT broker vs the Arduino Wifi library vs the SDK API, the most efficient design was the SDK API. While all 3 methods worked well, the SDK design uses a callback to service client connections without any code needed in the loop() function.

The Arduino Wifi library requires polling for connections each iteration of loop().

And sure, the MQTT broker server, like the SDK API, also uses callbacks. But it still requires the execution of “client.loop()” in the sketch’s loop() function. This consumes bandwidth which undoubtedly will add latency to other tasks added to loop().

If loop() latency becomes an issue in your sketch, use of the SDK API web server callbacks will minimize the delays.

Response Delay Evaluation

A simple web page, using only html and JavaScript was used to measure the delay from the time a request was sent to the time the reply was received. The web page file is called “mqtt_server.html”; it is on GitHub here.

The time starts when the button is clicked to send a request to the server. When the reply is received, the end time-stamp was captured. But what I found was that this end stamp was not saved immediately, resulting in inaccurate readings. This is likely due to the asynchronous nature of JavaScript. To correct this, a 1 second callback was added from the time the reply time-stamp was captured to the time the lapse time was calculated. This resulted in repeatable results which appear to accurately report the response delay.

Twelve requests were made for each of the three server setups. The average of the twelve, and the average of ten with the high and low readings removed are shown in this table:

Sample 1 429 89 341
Sample 2 457 32 362
Sample 3 367 30 338
Sample 4 441 85 383
Sample 5 365 42 375
Sample 6 400 28 417
Sample 7 465 26 343
Sample 8 489 445 333
Sample 9 620 42 566
Sample 10 358 32 339
Sample 11 731 212 325
Sample 12 432 29 432
Average of 12 463 91 380
Average of 10(w/o Hi & Lo) 447 62 366

The time is measured in milliseconds. From this experiment, it is clear that the SDK API offers significantly less latency than either the Wifi Library or MQTT. From this, it should be clear that callbacks that do not use the sketch loop() function are more efficient.

In Closing

There are advantages and shortcomings when using either MQTT or http for web server applications. MQTT offers a clean and simple code interface, but it does require the use of a broker. That adds an additional layer of complexity and potential failure to your system.

In my opinion, MQTT is best suited to be used for data distribution, not as a web server. The MQTT publish/subscribe model works great to simultaneously send information from one source to many consumers. If speed is critical, the EspressIf SDK API is the best option to use the ESP8266 as a web server.


Share This:
Social tagging: > >

7 Responses to ESP8266 HTTP vs MQTT Servers

  1. Jerzy says:

    Great comparison, thank you. But why is there such a difference between callbacks and polling? Iterating through an idle loop should be really fast. And could you also test CoAP? It should perform well, since it is based on UDP.

    • facebook-profile-picture InternetOfHomeThings says:

      Thanks for your comment Jerzy. Callback always tend to be more efficient than polling. We also do not know exactly all the tasks loop() services between each iteration…under the hood.

      I also apprecieate your bringing my attention to CoAP. I checked it out, for my first time, and added it to the server for a side-by-side comparison. The results are in this post.

  2. AndyW says:

    Hi, have you looked at the ESP8266WebServer in the ESP8266 Arduino standard library set ? Supports the event driven callback approach which as you mention is much more elegant than a big polling/parsing/decision block.

    Here’s a simple example using the library

    • facebook-profile-picture InternetOfHomeThings says:

      Thanks for your comment and information. I am aware of the Web server library but have not used it…yet. It would be great to hear of anyone’s experience regarding stability and heap usage using ESP8266webserver.

  3. Mark Stevens says:

    I did a test of polling once per second in loop(), which I implemented by a Chromo.h timer (e.g. each time the seconds changed I called a processHTTP() function. I did this because my program advances an LED display and emits a short "beep" at every second change. Most of the time this works fine (average 60ms) but when I get a blank HTTP request (e.g. "" after applying string.trim() ) it takes just over a second, which causes a noticable hickup in the clock/beeper.

    This is the same issue I just posted in post. I'm only posting it twice, but the in the context of this discussion I thought it was applicable as another option to work around this issue in similar situations.

  4. Guillermo Vides says:

    I could not compile your projects. the problem is redeclaration of several functions in webserver/memmanager.h previously declared in esp8266core.I am using esp8266 core v2.3 and I've tested then with Arduino ide 1.83 and 1.68.
    thanks in advance

    • facebook-profile-picture InternetOfHomeThings says:

      Using Arduino 1.8.2, I was able to compile the project by updating the prototype for external function pvPortZalloc which changed since this was initially posted.

      //void * pvPortZalloc(int size);
      void * pvPortZalloc(int size,char *, int);

      Please also not that the library PubSubClient has been added to the repository as it was initially missing. This library must be added to your Arduino IDE library for the project to compile.

Leave a Reply