slonik

A strictly-typed Node.js PostgreSQL client with runtime validation, safe connection handling, and composable raw SQL.

Library
npm
v49.10.9
4,936stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
78/100Good
Development Activity68
Maintenance88
Community56
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
80/100Excellent
Architecture88
Code Quality85
Innovation78
Learning Curve70

Slonik is a Node.js PostgreSQL client built on top of node-postgres that promotes writing raw SQL instead of hiding it behind an ORM’s query builder. It wraps the underlying driver with strict connection and transaction lifecycle handling — connections can only be checked out for the duration of a callback, which prevents the classic bug of a connection leaking forever after an unhandled error.

What sets Slonik apart from a bare pg client is its layer of assertions and type safety. Query methods like one, many, maybeOne, and oneFirst encode the expected shape of a result directly into the method name, throwing descriptive errors (NotFoundError, DataIntegrityError) the moment a query returns an unexpected number of rows or columns, instead of letting bad data silently flow downstream. Combined with a sql tagged-template tag that supports runtime schema validation via Standard Schema (Zod, Valibot, etc.), interceptors for logging and query caching, and automatic transaction/query retrying, Slonik is aimed at teams who want the safety net of an ORM without giving up hand-written SQL.

What You Get

  • A sql tagged-template tag for composing raw, injection-safe SQL with typed value placeholders (sql.array, sql.identifier, sql.json, sql.unnest, etc.)
  • Assertive query methods (one, oneFirst, many, manyFirst, maybeOne, exists) that throw precise errors (NotFoundError, DataIntegrityError) instead of letting malformed results propagate
  • Automatic connection lifecycle safety — connections are checked out only for the duration of a callback and always released, with configurable connection reset (DISCARD ALL) between uses
  • Runtime result validation via Standard Schema (Zod, Valibot) so a query’s declared output type is checked, not just assumed, at execution time
  • Built-in transaction nesting, transaction retrying, and query retrying for handling serialization failures and transient errors without hand-rolled retry loops
  • An interceptor system for logging, query result caching, and field-name transformation, plus a modular monorepo split (@slonik/driver, @slonik/pg-driver, @slonik/errors, @slonik/sql-tag) so the driver layer is swappable

Common Use Cases

  • Backend services that need direct, auditable SQL against PostgreSQL without adopting a full ORM’s abstraction and migration system
  • High-throughput data pipelines and warehousing workloads where connection and transaction handling must be provably leak-free at scale
  • APIs that validate query results against a schema (Zod) at runtime to catch drift between the database and application-level types
  • Codebases migrating off pg, pg-promise, or knex that want stricter guarantees around connection release and result-shape assertions
  • Systems that need query-level retry behavior for transient PostgreSQL errors (serialization failures, connection drops) without custom retry code

Under The Hood

Architecture Slonik’s monorepo separates a driver-agnostic core (packages/slonik) from the actual PostgreSQL wire implementation (@slonik/pg-driver, built on node-postgres) via a DriverFactory interface, so createPool in src/factories/createPool.ts composes a driver, a connection pool (createConnectionPool), and a public API (bindPool) without the core package depending on pg directly. bindPool and bindPoolConnection/bindTransactionConnection in src/binders/ wrap the low-level pool into the public DatabasePool/DatabaseConnection objects, routing every call through createConnection (src/factories/createConnection.ts) which enforces the checkout-for-duration-of-callback pattern. Query-shape assertions live in src/connectionMethods/ (one.ts, many.ts, oneFirst.ts, etc.), each a thin wrapper around a shared query/record routine, while src/routines/establishConnection.ts and executeQuery.ts handle the actual round-trip and stack-trace capture. Transaction nesting is tracked via src/contexts/transactionContext.ts. The result is a clear layered design: driver → connection pool → connection binding → assertive query methods, with each layer independently testable.

Tech Stack Written in TypeScript (98% of the codebase) targeting Node.js 24+, using ESM (type: module) throughout. The core package depends on @opentelemetry/api for tracing hooks, zod and @standard-schema/spec for runtime result validation, p-queue for connection-pool concurrency control, roarr for structured logging, and serialize-error for safely serializing thrown errors. The workspace is split into scoped packages (@slonik/driver, @slonik/pg-driver, @slonik/errors, @slonik/sql-tag, @slonik/types, @slonik/utilities) managed via pnpm workspaces and released together with Changesets. Linting uses oxlint/oxfmt (Rust-based tooling) plus knip for dead-code detection, and cspell for spell-checking docs and source.

Code Quality The slonik package alone has 31 test files (both *.test.ts files and *.test/*.test.ts directories like helpers.test/, integration.test/, binders/bindPool.test/) run with ava in serial mode, exercising real PostgreSQL connections via a shared createTestRunner helper, including expect-type assertions for compile-time type checks alongside runtime behavior tests. tsconfig.json enables strict: true with noImplicitReturns, giving strong compile-time guarantees. Errors are represented as a typed hierarchy (SlonikError subclasses like NotFoundError, DataIntegrityError, UniqueIntegrityConstraintViolationError) rather than generic exceptions, and CI runs via GitHub Actions workflows (feature.yaml, main.yaml) covering lint and test stages.

What Makes It Unique Rather than hiding SQL behind a query builder or full ORM, Slonik deliberately keeps SQL as the primary interface while adding the safety nets ORMs are usually praised for — connection-leak prevention by construction, assertive result-shape methods that fail loudly and specifically, and runtime schema validation of query results via Standard Schema rather than only compile-time types. Its interceptor system and swappable driver factory also let teams substitute pooling, logging, or even the underlying wire protocol without touching call sites, which is unusual for a library that otherwise reads like a thin SQL client.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search