elasticsearch-js: the official Node.js client, and what its versioning rules cost you
Official Elasticsearch client library for Node.js
At a glance
- What is it?
- The official Elasticsearch client library for Node.js is a generated, typed HTTP client that tracks the Elastic Stack release schedule rather than the Node.js one. Here is how it installs, how far its compatibility promise actually goes, and when a plain HTTP call is the better choice.
- Who is it for?
- Adopt @elastic/elasticsearch if you run a supported Node.js version, talk to an Elasticsearch 9.x cluster, and want generated types for every API. Do not adopt it for browser code: the README states there is no official browser support and recommends a lightweight proxy instead.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem elasticsearch-js solves, and who actually needs it
Elasticsearch speaks HTTP and JSON, so a Node.js service can talk to it with fetch and a few string templates. That works until the query DSL grows. A search request with an aggregation tree, a bulk body, and a per-request timeout is a large JSON object that nothing validates, and a typo in a field name comes back as a runtime error from the cluster rather than a compile error in your editor.
The client exists to close that gap. It is the official Node.js client, published as @elastic/elasticsearch, and it ships a typed surface for the Elasticsearch API plus connection handling that a hand-rolled wrapper would have to reimplement: node discovery, retries, and a pluggable transport. The audience is Node.js and TypeScript backend teams that already run Elasticsearch and want the API surface checked at build time. It is not a query builder and not an ORM. You still write the query DSL yourself; the client tells you when the shape is wrong.
Generated API methods and the transport underneath them
The repository layout separates the two halves of the package. The src/ directory holds the transport and the client core, while the API methods are generated from the Elasticsearch specification and exposed through index.js with index.d.ts as the type entry. The package.json exports map is explicit about this split: the root export resolves to ./esm/index.js for import and ./index.js for require, with ./index.d.ts for types, and subpaths under ./lib/* follow the same import/require/types pattern. The package is typed as commonjs at the top level while still publishing an ESM build.
That structure explains the compatibility table in the README. Because the methods are generated from a specific Elasticsearch version, the client cannot know about endpoints that did not exist when it was generated. The README states the clients are forward compatible, meaning they can talk to greater or equal minor versions without breaking, but it is explicit that this does not mean the client supports new features of newer Elasticsearch versions automatically. A 8.12 client will not support 8.13 features; you need the 8.13 client for that. Backwards compatibility is limited to default distributions and comes without guarantees.
The practical consequence is that upgrading the cluster and upgrading the client are two separate tasks that have to be sequenced. If you point a 9.5 client at a cluster that has moved ahead, the requests you already wrote keep working, but any new endpoint is simply absent from the generated types.
Installing elasticsearch-js and running a first search
The README does not inline the install command. It points to the Installation section of the getting started documentation, and the package name in package.json is @elastic/elasticsearch. The minimum supported Node.js version is v20. If you want a local cluster to point at, the README gives a single command that starts Elasticsearch on port 9200 and Kibana on port 5601.
curl -fsSL https://elastic.co/start-local | shOnce a cluster is reachable, the client is created with a node URL. The README links a Connecting section for the full options, and the client configuration page covers the rest. The README's usage list is the order to work through: creating an index, indexing a document, getting documents, searching, updating documents, deleting documents and deleting an index. Each of those links to a worked example in the getting started guide rather than appearing in the README itself, so the repository is a pointer to the documentation rather than a substitute for it. If you are evaluating the client without a cluster of your own, that is the sequence to read.
The browser warning is a real boundary, not boilerplate
The README carries a warning block stating there is no official support for the browser environment, because running the client in a browser exposes your Elasticsearch instance to everyone and can lead to security issues. The recommendation is to write a lightweight proxy that uses this client instead, and the repository includes a proxy example under docs/examples/proxy.
This is the clearest case where the client is the wrong tool. A frontend that calls Elasticsearch directly, even with credentials embedded, hands those credentials to every visitor, and Elasticsearch's own access controls are not designed to be a public API gateway. The proxy pattern the README points at keeps the client on the server and gives the browser a narrower surface. If your architecture assumes a browser-side search client, plan the proxy before you plan the client.
Node.js version support moves on its own schedule
The README is unusually direct about a maintenance cost that most client libraries hide. Client versioning follows the Elastic Stack versioning, so major, minor and patch releases follow a schedule that often does not coincide with Node.js release dates. To avoid supporting insecure and unsupported Node.js versions, the client drops support for end-of-life Node.js versions between minor releases, typically keeping a version alive for at least one more minor release after it goes EOL, and logging a warning two minors in advance.
The compatibility table makes the pattern concrete. Node 16 went EOL in September 2023 and support ended at 8.11 in late 2023. Node 18 went EOL in April 2025 and support ended at 9.1 in mid 2025. That means a minor upgrade of the client can remove support for a Node version you are still running, which is why the README recommends defining the dependency with ~ instead of ^ in package.json for anyone not always on a supported Node version. Tilde pins the minor release, so ~7.10.0 rather than ^7.10.0.
That recommendation is worth taking literally. A caret range lets a patch or minor release arrive that has already dropped your Node version, and the failure shows up at runtime rather than at install time.
What you give up compared with calling the REST API directly
The alternative is not another Node client so much as no client at all: issue HTTP requests against the REST API with fetch or a small HTTP wrapper, and keep the query bodies as plain objects. The difference in approach is where the knowledge lives. With the client, endpoint names, parameter names and response shapes are generated from the Elasticsearch specification and checked by TypeScript, and the transport handles retries and node selection. With raw HTTP, you own the URL construction, the JSON serialization, the retry policy and the error parsing, and nothing tells you that a field name is wrong until the cluster rejects the request.
Raw HTTP wins in two situations the client does not serve well. A worker that calls one or two endpoints with a fixed body does not need the generated surface, and adding a dependency with a versioning schedule tied to the Elastic Stack adds upgrade work for no benefit. And any environment where the client's Node.js floor is a problem is better served by a plain HTTP call than by pinning an old client release. The trade is real in both directions: the client buys you type checking and transport behaviour, and it charges you a compatibility table you have to keep reading.
Licence and the cost of keeping up
The package is Apache-2.0, and the repository carries both LICENSE and NOTICE.txt at the top level. Apache-2.0 permits commercial use and modification and includes a patent grant; the NOTICE file is the mechanism for attribution that the licence expects you to preserve when redistributing. That is a description of the licence text, not legal advice, and any organisation with a licence review process should run it through that process rather than treating this paragraph as clearance.
The upgrade cost is the more practical number. The client's minor releases are tied to Elastic Stack releases, and the README states that end-of-life Node.js versions are dropped between minor releases. So the work is not optional maintenance you can defer indefinitely; it is a periodic check of two tables, the Elasticsearch version compatibility table and the Node.js end-of-support table, followed by either a client bump or a Node.js bump. Teams that pin with ~ absorb this in small steps. Teams that pin with ^ and run an old Node version find out when a release lands.
Editorial conclusion
Adopt @elastic/elasticsearch if you run a supported Node.js version, talk to an Elasticsearch 9.x cluster, and want generated types for every API. Do not adopt it for browser code: the README states there is no official browser support and recommends a lightweight proxy instead. Do not adopt it if you must stay on Node 18, which the compatibility table lists as out of support from 9.1. Before writing code, check the compatibility table against your exact Elasticsearch minor, and pin the dependency with ~ rather than ^ if your Node version is close to EOL.
Frequently asked questions
Is Elasticsearch a SQL or NoSQL database?
Elasticsearch is not a relational database and the client exposes no SQL surface; it is the official Node.js client for the Elasticsearch API, and the README's usage list covers index creation, indexing, getting, searching, updating and deleting documents. Whether you call that NoSQL is a labelling question the repository does not answer.
Can I use Elasticsearch in Java?
This repository is the Node.js client and does not cover Java. The README is scoped to Node.js, states a minimum supported Node.js version of v20, and links only to JavaScript client documentation.
How do I install the Elasticsearch Node.js client?
The README does not inline the install command; it points to the Installation section of the getting started documentation, and the package name in package.json is @elastic/elasticsearch. The minimum supported Node.js version is v20.
Can I use the Elasticsearch JavaScript client in a browser?
No. The README warns that there is no official browser support because it exposes your Elasticsearch instance to everyone, which could lead to security issues, and recommends writing a lightweight proxy that uses the client instead.
Which Node.js versions does the Elasticsearch JS client support?
The minimum supported version is v20. The README states that the client drops support for end-of-life Node.js versions between minor releases, and its table lists Node 18 as ending support at 9.1.
Which Elasticsearch version does this client work with?
The README's compatibility table maps Elasticsearch 9.x to the 9.x branch, 8.x to 8.x and 7.x to 7.x. Clients are forward compatible with greater or equal minor versions, but new features of a newer Elasticsearch version require a newer client.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/elastic-elasticsearch-js)