Implement HTTP Streaming with Node.js and Fetch API
Do you know that you can stream HTTP data for efficient visualization? Learn more about how you can stream data with HTTP using Node.js and Fetch API.

Table of Contents
- Introduction
- Create a Streaming API
- Consume a Streaming API From a Webapp
- HTTP/2 for Streaming
- HTTP Streaming Considerations
- Advantages
- Disadvantages
- Conclusion
Introduction
When your webapp has a large amount of data to visualize, you don't want your users to wait 10 seconds before seeing something.
One technique that is often overlooked is HTTP streaming. It's broadly supported, works well, and doesn't require fancy libraries.
We're going to go through how we can use HTTP streaming in our applications and what to consider when we do so.
Introduction
When building web applications, we typically have a REST API with GET endpoints that do something like this:
- Parse the request (URL, query params, etc..)
- Query data from a database
- Convert the database results into JSON
- Send the JSON response back
The API will typically wait for each step to complete before going on to the next one, and by step 4, the database result and the JSON objects are all in memory before the request is handled, and everything can be cleaned up.
This works, and there is nothing wrong with it (KISS, right?) as long as your database query results are small and quickly available.
But let's say you want to render a chart with 10k data points. Querying will not be as smooth anymore. The simple way will work, but ideally, you don't want to accumulate all the data in memory before sending the response.
With HTTP streaming, you can start rendering the chart even before your query is complete.
To make it happen:
- Your API should use HTTP streaming to send its response.
- Your webapp should use the Fetch API to make the request so that it can process the streaming response.
Create a Streaming API
In this example, we use Koa for the API, but you can use other libraries like Express or plain Node.js. Most will have support for streaming.
Let's create an API:
This code creates an API with 1 endpoint that will respond with the contents of a JSON file with 10k measurements.
The file looks like this:
We're creating an HTTP/1.1 server with Node's module. By setting to a stream, data will be sent to the requester as soon as it is loaded using a mechanism called chunked transfer encoding.
This saves time and memory of your API because it doesn't have to accumulate the whole result in memory before sending the response.
In a real application, you're probably using a database instead of a pre-created JSON file. If you're using MongoDB, you can create a stream with the cursor's method.
Consume a Streaming API From a Webapp
The endpoint we created can be consumed with any HTTP client, but you have to use the Fetch API to take advantage of streaming.
will set to a ReadableStream for streaming responses.
Here's how you can read a streaming response:
If you run the API that we created and then run the code above in a web browser, you'll see several times in the console with varying x:
To see it more clearly, open up Developer Tools (F12) and set network throttling to 3G. It will take longer for the file to download, so you can see that the chunks are being processed gradually.
That's all very nice, but the chunks themselves are not very useful. You want to process the measurements that are in these chunks. Ideally, you would have an async iterable that gradually yields the JSON objects as they come in so that you can use to iterate over the measurements instead of the chunks.
JavaScript doesn't have a JSON parser that can deal with streams. Let's assume we have a function that can do this called . More details and a simple implementation can be found in "Streaming Considerations" below.
We would then be able to do this:
This is the result:
This is a very powerful mechanism. Instead of statements, imagine a line chart where the measurements gradually become visible as more data comes in.
This is an example created with Apache ECharts:
Before the Fetch API, it was impossible to do this because the alternative, , will load the whole response into memory before providing it to your code.
Modern applications don't use directly, but a lot of libraries like Axios or Angular's HttpClient rely on it to make requests.
People would rely on more advanced technologies like WebSockets to stream data.
HTTP/2 for Streaming
You might have heard that HTTP/2 has a more efficient mechanism for streaming, and you would be right. So let's see if we can use HTTP/2.
From the side of your webapp, the browser will automatically determine if it can communicate with the server over HTTP/2 and use it if it's available. The Fetch API will do this transparently, so you do not need to make any changes to your webapp.
What you need to do is make your API available over HTTP/2:
This code is mostly the same as for HTTP/1.1 with two notable differences:
- We're using Node's module instead of .
- We're using instead of plain because this is mandatory for HTTP/2. You can set up HTTPS and get the and files using mkcert. Or, use one of the other mechanisms described in this article: Use HTTPS for Local Development
That's it!
If you restart the API and check the network tab in Developer Tools, you'll see that your application will now stream over HTTP/2 (don't forget to update the URL in your webapp, start with instead of ).
HTTP Streaming Considerations
In the code above, we assumed that there was a function that would parse a containing JSON into an async iterable of objects.
The difficulty is that reading from a will give you chunks of data that don't necessarily correspond to anything meaningful. To illustrate, let's take a look at this example:
We could receive this JSON in chunks like this:
You need some way to determine where one measurement object starts and ends. To simplify this, we created a JSON file where each line contains precisely one object. Parsing the stream becomes manageable when we can make this assumption.
Here is the implementation of
If you have control over the API you're calling, you can use the "1 object per line" formatting as part of the contract, but know that it could be prone to breaking. For robust JSON support, we need a real streaming parser.
Other options include using a format with one object per line by default, like CSV, or a more advanced format with built-in support for streaming like Apache Arrow.
Advantages
- Snappy User Experience: You can start showing data as soon as it's available.
- Scalable API: No memory usage spikes from accumulating results in memory.
- Uses plain HTTP and a standard JavaScript API. There are no connections to manage or complicated frameworks that might become obsolete in a few years.
Disadvantages
-
Implementation is slightly more involved than using regular API calls.
-
Error handling becomes more difficult because HTTP status code 200 will be sent as soon as streaming starts. What do we do when something goes wrong in the middle of the stream?
When something goes wrong, your API should close the stream. Your webapp can then determine if the stream was complete and show a fitting message to the user if it's not. For example: when using a JSON response, as we discussed, you can check that the last line contains only "]".
-
No streaming JSON parser is currently available. Needs formatting assumptions as part of the contract or a more unconventional format.
Conclusion
You have learned how to stream HTTP data efficiently using Node.js and HTTP without congesting or burdening the memory. You have also understood the advantages and disadvantages of HTTP streaming.

Featured Posts
How to Implement JWT Authentication for CRUD APIs in Deno
Multi-Factor Authentication (MFA) with Redis Cache and OTP
Introduction to SolidJS
Build a Modern Login/Signup Form with Tailwind CSS and React
Implement HTTP Streaming with Node.js and Fetch API
NestJS: How to Implement Session-Based User Authentication
NestJS User Authentication with LoginRadius API
How to Authenticate Svelte Apps
Flutter Authentication: Implementing User Signup and Login
How to Secure Your LoopBack REST API with JWT Authentication
Node.js User Authentication Guide
Your Ultimate Guide to Next.js Authentication
Local Storage vs. Session Storage vs. Cookies
How to Secure a PHP API Using JWT
Using JWT Flask JWT Authentication- A Quick Guide
Build Your First Smart Contract with Ethereum & Solidity
What are JWT, JWS, JWE, JWK, and JWA?
How to Build an OpenCV Web App with Streamlit
32 React Best Practices That Every Programmer Should Follow
How to Build a Progressive Web App (PWA) with React
Bootstrap 4 vs. Bootstrap 5: What is the Difference?
JWT Authentication — Best Practices and When to Use
What Are Refresh Tokens? When & How to Use Them
How to Upgrade Your Vim Skills
How to Implement Role-Based Authentication with React Apps
How to Authenticate Users: JWT vs. Session
How to Use Azure Key Vault With an Azure Web App in C#
How to Implement Registration and Authentication in Django?
11 Tips for Managing Remote Software Engineering Teams
Implementing User Authentication in a Python Application
Add Authentication to Play Framework With OIDC and LoginRadius