DuckDB Async NodeJS Wrappers
duckdb-async provides Promise-based and TypeScript-first wrappers for the DuckDB NodeJS API, allowing developers to interact with DuckDB databases using modern `async/await` patterns instead of traditional callbacks. Currently at version 1.4.2, its releases have historically aligned with the `duckdb-node` module, which it depends on. A key differentiator is its comprehensive TypeScript support and the conversion of most callback-driven methods in `duckdb-node`'s `Database`, `Connection`, and `Statement` classes into promise-returning equivalents. Notably, the `Database` constructor is replaced by a static `Database.create()` factory method to accommodate async initialization. However, it's critical to note that `duckdb-async` is currently in a deprecated state; the maintainers have announced that it, along with `duckdb-node`, will not be released for DuckDB 1.5.x (~Early 2026) and subsequent versions. Users are advised to migrate to the newer `@duckdb/node-api` package for ongoing support and future compatibility.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'all') at new Database
cause Attempting to instantiate `Database` directly with `new Database(...)`.fixThe `Database` constructor is callback-based. You must use the static asynchronous factory method `await Database.create(...)` instead of `new Database(...)` to correctly initialize the database. -
TypeError: db.each(...).then is not a function
cause Attempting to use `await` or `.then()` directly on the `each` method, which is callback-based.fixThe `each` method does not return a Promise. Pass a callback function as an argument: `db.each('SELECT * FROM users', (err, row) => { /* handle row */ });`.
Warnings
- breaking The `duckdb-async` package, along with `duckdb-node`, is explicitly deprecated by the maintainers in favor of the new `@duckdb/node-api` package. Future DuckDB versions (1.5.x onwards, ~Early 2026) will not be supported by `duckdb-async`.
- gotcha The `each` method on `Connection`, `Database`, and `Statement` classes retains its original callback-based interface and does not return a Promise. This is because promises resolve once, while `each` invokes a callback for every row.
Install
-
npm install duckdb-async -
yarn add duckdb-async -
pnpm add duckdb-async
Imports
- Database
import Database from 'duckdb-async';
import { Database } from 'duckdb-async'; - Connection
const { Connection } = require('duckdb-async'); // Incorrect for modern ESM/TypeScript projectsimport { Connection } from 'duckdb-async'; - Statement
const Statement = require('duckdb-async').Statement; // Less common CJS import patternimport { Statement } from 'duckdb-async'; - CommonJS require
const { Database, Connection } = require('duckdb-async');
Quickstart
import { Database } from "duckdb-async";
async function simpleTest() {
const db = await Database.create(":memory:");
// Example of using a query with parameters
const rows = await db.all("select * from range(?,?)", 1, 10);
console.log('Query Result:', rows);
// Example of a run operation (e.g., DDL or DML without returning rows)
await db.run("CREATE TABLE items (id INTEGER, name VARCHAR)");
await db.run("INSERT INTO items VALUES (?, ?)", 1, 'Apple');
await db.run("INSERT INTO items VALUES (?, ?)", 2, 'Banana');
const allItems = await db.all("SELECT * FROM items");
console.log('All Items:', allItems);
// Close the database connection (important for file-based databases)
await db.close();
}
simpleTest().catch(console.error);