# Dec 9th, 2025: \[EN\] Use the Node.js Elasticsearch client to index large CSV files

**URL:** <https://discuss.elastic.co/t/dec-9th-2025-en-use-the-node-js-elasticsearch-client-to-index-large-csv-files/382901>\
**Category:** Advent Calendar\
**Created:** [December 9, 2025, 8:00am UTC](https://discuss.elastic.co/t/dec-9th-2025-en-use-the-node-js-elasticsearch-client-to-index-large-csv-files/382901 "2025-12-09T08:00:33Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![joshmock](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/joshmock/32/119294_2.png) [@joshmock](https://discuss.elastic.co/u/joshmock)\
**Post date:** [December 9, 2025, 8:00am UTC](https://discuss.elastic.co/t/dec-9th-2025-en-use-the-node-js-elasticsearch-client-to-index-large-csv-files/382901/1 "2025-12-09T08:00:33Z")

</div>

![social-advent-2021-Day9](https://us1.discourse-cdn.com/elastic/original/3X/d/4/d47e78f78ff2b06a54798ba4ac7225000630c538.jpeg)

Indexing a large number of documents into Elasticsearch is made straightforward using [the bulk API](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-bulk): transform your data records into JSON documents, interleaved with instructions for which index they should be added to, and send a single HTTP request to your Elasticsearch cluster with this large newline-delimited JSON blob as the body. Or, using the Node.js client’s `bulk` function.

Let’s read a CSV file, transform its rows into JSON objects, and index it:

```typescript
import { Client } from '@elastic/elasticsearch'
import { parse } from "csv-parse/sync"
import { readFileSync } from 'node:fs'

const csv = parse(readFileSync('data.csv', 'utf8'), { columns: true })
const operations = csv.flatMap(row => [
  { index: { _index: "my_index" } },
  row
])

const client = new Client({ node: 'http://localhost:9200' })
await client.bulk({ operations })

```

But what if you need to send more data than Elasticsearch can receive in a single request? Or your CSV file is so large that it can’t all fit into memory all at once? [Bulk helper](https://www.elastic.co/docs/reference/elasticsearch/clients/javascript/client-helpers#bulk-helper) to the rescue!

While the bulk API is simple enough to use on its own, for more complicated scenarios, the helper adds support for streaming input, breaking up large datasets into multiple requests, and more.

For example, if your Elasticsearch server can only receive HTTP requests smaller than 10MB, you can instruct the bulk helper to break up your data by setting a `flushBytes` value. This will send a bulk request every time the request is about to exceed a set value:

```typescript
const csv = parse(readFileSync('data.csv', 'utf8'), { columns: true })
await client.helpers.bulk({
  datasource: csv,
  onDocument(doc) {
    return { index: { _index: "my_index" } }
  },
  // send a bulk request for every 9.5MB
  flushBytes: 9500000
})

```

Or if your CSV file is too large to fit in memory, the helper can take a [stream](https://nodejs.org/api/stream.html) as its `datasource` instead of an array:

```typescript
import { createReadStream } from 'node:fs'
import { parse } from 'csv-parse'

const parser = parse({ columns: true })
await client.helpers.bulk({
  datasource: createReadStream('data.csv').pipe(parser),
  onDocument(doc) {
    return { index: { _index: "my_index" } }
  }
})

```

This will buffer rows into memory from the CSV file, parse them into JSON objects, and let the helper flush the results out into one or more HTTP requests for you. Not only is this solution easy on memory, but it’s just as easy to read than the solution that loads the entire file into memory!
