Library / SDK
brianc/node-postgres avatar
brianc/node-postgres

node-postgres: the pg client for Node.js, and when a raw driver beats an ORM

PostgreSQL client for node.js.

13,236 stars1,387 forksJavaScriptMIT

At a glance

What is it?
node-postgres is the PostgreSQL driver behind the npm package pg, a pure JavaScript client with optional native libpq bindings and a separate pooling module. It is a driver, not an ORM, and that distinction decides whether it fits your project.
Who is it for?
Adopt node-postgres when you want SQL you write yourself, a pool you control, and no query builder between your code and PostgreSQL; the README's own description of the project as light on abstractions is the honest summary of that trade.
Can I use it commercially?
Yes. MIT 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 23 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • brianc/node-postgres13,236 ★ · +27
Star history
Repository2026-09-222026-11-14
brianc/node-postgres13.2k13.2k

27 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

What problem node-postgres solves, and for whom

The README describes node-postgres as a non-blocking PostgreSQL client for Node.js, with the same code intended to run on bun, deno and cloudflare workers. The npm package is pg. That is the whole product: a client that speaks the PostgreSQL wire protocol from JavaScript and hands you rows.

The audience is narrower than the download numbers suggest. If you are comfortable writing SQL, want to see exactly what reaches the server, and would rather compose queries in your own code than learn a query builder's dialect, this is aimed at you. The README is explicit that node-postgres is by design pretty light on abstractions, and that the modules completing the picture live on a wiki page rather than in the repository. Anything resembling a model layer, a migration runner or a relationship mapper is outside the package.

The monorepo layout makes the boundaries visible: packages/pg holds the client, packages/pg-pool the pool, packages/pg-native the libpq bindings, packages/pg-cursor and packages/pg-query-stream the streaming paths, plus pg-connection-string and pg-protocol. Choosing node-postgres means choosing to assemble those pieces yourself.

How the pg client and pg-pool actually work

A single pg.Client maps to one connection. A pg.Pool keeps several connections open and hands one to each query you run through it, which is why the client versus pool question comes up so often. The pool lives in its own package in this repo, so the pooling behaviour is not hidden inside the client.

The README lists the PostgreSQL features the client exposes: parameterized queries, named statements with query plan caching, asynchronous notifications through LISTEN/NOTIFY, and bulk import and export through COPY TO and COPY FROM. Named statements are the mechanism behind plan reuse, so repeated queries with the same name avoid re-planning on the server.

Two design points shape how the code reads. Data-type coercion between JavaScript and PostgreSQL is extensible, meaning you register your own parsers for types the defaults do not handle the way you want. And the pure JavaScript client and the native libpq bindings share the same API, so pg-native is a drop-in for the same calls rather than a second client with its own surface. The README also links a third-party benchmark repository when it calls this the fastest PostgreSQL client for Node.js; that claim comes from outside the project, and the repository's own benchmark/ directory holds a comparison script you can read rather than a published result.

Installing pg and running a first pooled query

The install step in the README is one command. It pulls the pg package from npm.

bash
npm install pg

After that, the README does not print a usage sample of its own. It says each package in the repo should have its own readme focused on how to develop and contribute, and that overall documentation for the project and the related modules lives at node-postgres.com, with the docs source in the repository's docs/ directory. So the first real query is a trip to node-postgres.com rather than something the README walks you through.

What the README does give you for connecting is the environment. Its local development steps say to ensure the proper environment variables are configured for connecting to your postgres instance, using the standard PG* environment variables like PGUSER and PGPASSWORD. Those are the same names the client reads at runtime, so the connection details you set up for tests are the ones your application uses.

For a large export, the COPY path avoids materializing the whole result in memory, and the README lists COPY TO and COPY FROM as supported features. The streaming route through pg-query-stream and pg-cursor is the other option the monorepo provides. Neither has an example in the README; the package readmes and the docs repository are where the exact call shape lives.

Where node-postgres is the wrong tool

The clearest limitation is the one the README states as a design choice: few abstractions. There is no migration system in the pg package, no schema definition file, no generated types. If your team wants the database schema expressed in code and migrations applied by the same tool, node-postgres does not provide that, and the extras wiki is a list of community modules rather than a blessed stack.

Type coercion is the second place teams get surprised. Because JS to PostgreSQL coercion is extensible rather than fixed, what a column comes back as in JavaScript depends on the parsers registered for that type. That is flexible and it is also a configuration surface you own.

The native bindings are a deployment constraint, not a free speedup. The README's local development steps require libpq-dev on the system because the native bindings are built during the test process, and it notes that SSL-dependent tests can be skipped by setting PGTESTNOSSL=1. A build environment that cannot compile native code is a reason to stay on the pure JavaScript client, and the shared API means that switch does not change your query code.

Finally, the README does not document rollback, retry or transaction helpers. If you need those, they are yours to write.

node-postgres versus an ORM or a query builder

The common comparison is node-postgres against Prisma or Sequelize, and the difference is not performance, it is who owns the SQL. An ORM generates queries from a model definition and gives you migrations and typed results as part of the package. node-postgres executes the SQL you supply and returns rows; the shape of those rows is whatever the database sends back.

That changes the failure modes. With an ORM, a slow query is often something the generated SQL did, and your lever is the ORM's escape hatch. With node-postgres, the query text is in your repository, so EXPLAIN points straight at code you wrote. The cost moves to the other side: joins, transactions and schema evolution are manual work.

A second comparison, node-postgres against postgres.js, is a difference of packaging rather than of protocol. Both are JavaScript PostgreSQL clients; node-postgres splits the client, the pool, the cursor, the stream and the connection-string parser into separate packages in a monorepo, while the README lists bun, deno and cloudflare as targets for the same client code. If you want one small dependency with everything inside, that packaging difference is the thing to weigh, not the feature list, since both speak to the same server.

Maintenance, licence and the upgrade cost you should budget

The repository is not archived, and the last push was on 2026-10-23. The README's contributing section states the compatibility rule directly: pull requests are accepted if they have tests, look reasonable and do not break backwards compatibility, and anything breaking should be flagged in the pull request so a release plan can be discussed. That is a stability promise and also a constraint, since it means API changes arrive slowly and deliberately.

The licence is MIT, with the copyright notice naming Brian Carlson. In practical terms the grant permits use, modification, sublicensing and sale, provided the copyright and permission notice are included and the software is passed on without warranty. That is the text in the README, not legal advice; if your organisation has rules about attributing bundled dependencies, the notice is the part to check.

Upgrade cost is concentrated in the monorepo's build. The root package.json defines build as tsc --build and runs it through pretest and prepublish, so the published packages are compiled from TypeScript sources. The root package is private and uses yarn workspaces plus lerna, with a test script that runs each package's tests at concurrency 1. If you consume only pg from npm, that machinery is invisible; if you fork or patch a package, you inherit it. The repository has no published GitHub releases, so treat the changelog in the repository as the source for version-to-version changes.

Editorial conclusion

Adopt node-postgres when you want SQL you write yourself, a pool you control, and no query builder between your code and PostgreSQL; the README's own description of the project as light on abstractions is the honest summary of that trade. Skip it if you need migrations, a schema definition language and typed models generated from the database, because none of those ship in the pg package and the extras list is a wiki page of community modules rather than a supported framework. Before committing, check whether your deployment can build the native bindings, since the README treats libpq-dev as a local development prerequisite rather than an optional extra.

Frequently asked questions

Is node-postgres an ORM?

No. The README describes it as a PostgreSQL client and says the project is by design light on abstractions, with related modules listed on a wiki page rather than bundled. There is no model layer or migration tool in the pg package.

How do I install node-postgres?

Install the npm package pg with npm install pg, which is the single install step the README gives. The package is the client; pooling comes from the pg-pool package inside the same monorepo.

What is the difference between the node-postgres client and the pool?

A client is one connection, while a pool keeps connections open and hands one to each query. The README lists connection pooling as a feature and the pool lives in its own package, pg-pool, in this repository.

What are the key differences between postgres.js and node-postgres?

Both are JavaScript clients for PostgreSQL. The packaging differs: node-postgres is a monorepo that splits the client, pool, cursor, stream and connection-string parser into separate packages, and its README lists bun, deno and cloudflare as targets for the same client code.

What is node-postgres used for?

It is used to run SQL against PostgreSQL from Node.js. The README lists parameterized queries, named statements with query plan caching, LISTEN/NOTIFY notifications, and COPY TO and COPY FROM bulk import and export as supported features.

Official sources

  1. brianc/node-postgres on GitHub
  2. Issues
  3. License: MIT
  4. Project website
  5. README
Community

Where developers are discussing it

Posts on Hacker News, dev.to and Lobsters that link to this repository, found by our scan of those communities. 1 in the last 30 days; newest first.

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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/brianc-node-postgres.svg)](https://hysenlabs.com/projects/brianc-node-postgres)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/brianc-node-postgres.svg)](https://hysenlabs.com/projects/brianc-node-postgres)

Was this useful?