mariadb
Non-blocking MariaDB and MySQL client for Node.js with promise and callback APIs, built for high-throughput production workloads.
Repository Health
Technical Analysis
mariadb is the official MariaDB Corporation-maintained Node.js connector for MariaDB and MySQL servers. Written entirely in JavaScript with first-class TypeScript definitions, it implements the MySQL/MariaDB binary wire protocol directly rather than wrapping a native driver, giving it full control over connection lifecycle, packet encoding, and streaming behavior.
Beyond basic query execution, it offers features many general MySQL clients lack out of the box: readable-stream-based INSERT streaming for large payloads without buffering everything in memory, command pipelining that sends queries back-to-back without waiting for each response, bulk/batch insert APIs, connection pooling and pool clustering, prepared-statement caching, and ed25519 plugin authentication support. It requires Node.js 20 or later as of 3.5.3 and ships both promise (default) and callback entry points for compatibility with legacy driver-style code.
What You Get
- Promise-based API by default (
require('mariadb')) plus a dedicated callback API (require('mariadb/callback')) for drop-in compatibility with older driver code - Connection pooling via
createPool()with automatic idle-connection management, and pool clustering viacreatePoolCluster()for multi-host failover/load balancing - Insert streaming: pass a Node.js Readable stream directly as a query parameter and the driver streams it to the server without buffering the full payload in memory
- Command pipelining that sends successive commands to the server without waiting for each result, reducing round-trip latency for sequences of statements
- Bulk/batch insert API for sending large numbers of rows in as few round trips as possible
- Prepared-statement caching (LRU) to avoid re-preparing identical queries, plus binary protocol execute() alongside text-protocol query()
- Zero-configuration SSL/TLS support and ed25519 plugin authentication
- First-class TypeScript type definitions (
.d.ts/.d.cts) shipped alongside both ESM and CJS builds
Common Use Cases
- Backend API servers - Express/Fastify/Nest-style Node.js services querying a MariaDB or MySQL database with pooled connections for concurrent request handling
- Bulk data ingestion pipelines - ETL-style scripts using the batch/bulk insert API to load large CSV/JSON datasets into MariaDB with minimal round trips
- Streaming large payloads into BLOB/TEXT columns - applications that pipe file or HTTP-response streams directly into INSERT statements without loading them fully into memory
- Multi-host/high-availability deployments - services using
createPoolCluster()to spread load or fail over across multiple MariaDB replicas - Migrating off
mysql/mysql2- teams switching from older MySQL-only clients to gain MariaDB-specific features while keeping a similar promise/callback API surface
Under The Hood
Architecture
The connector is organized around a Connection class (lib/connection.js) that owns socket I/O, send/receive command queues, and protocol state, wrapped by thin ConnectionPromise/ConnectionCallback facades (lib/connection-promise.js, lib/connection-callback.js) that adapt the same underlying connection to promise- or callback-style call sites. Pooling is layered on top via Pool/PoolPromise (lib/pool.js, lib/pool-promise.js), which manage idle/active connection sets, lazy connection creation up to connectionLimit, and request queuing when the pool is saturated; Cluster (lib/cluster.js) composes multiple named pools for multi-host failover. Protocol concerns are cleanly separated into lib/io/ (packet input/output streams, including a dedicated compression stream pair), lib/cmd/ (one command class per MySQL protocol command - query, prepare, execute, batch-bulk, change-user, etc. - plus lib/cmd/encoder and lib/cmd/decoder for binary/text row encoding), and lib/config/ (option classes for connections, pools, and clusters). This gives each protocol command a small, testable unit rather than one large monolithic client class, and it’s what makes features like insert streaming and pipelining possible without protocol-level hacks.
Tech Stack
The package is pure JavaScript (ESM type: module) with a CJS build produced via esbuild (dist/promise.cjs, dist/callback.cjs) so both import and require consumers get supported entry points, each with matching .d.ts/.d.cts TypeScript definitions generated by a custom tools/generate-cts.js script. Runtime dependencies are deliberately minimal: denque for efficient queue structures, iconv-lite for character-set conversion, lru-cache for prepared-statement caching, and @types/geojson/@types/node for typing spatial and Node APIs. It requires Node.js >= 20. Build/test tooling includes esbuild, TypeScript, ESLint (with eslint-plugin-security), Prettier, and Vitest.
Code Quality
The project has an extensive integration test suite (test/integration, dozens of files covering batch inserts, auth plugins, compression, cluster failover, prepared statements, datatypes, and more) plus a separate unit-test suite (test/unit) covering packet streams, command queues, and config parsing - run via Vitest with coverage collected through nyc/Codecov. CI (.github/workflows/ci.yml) gates every push/PR behind a fast lint stage (ESLint including eslint-plugin-security, Prettier, and full TypeScript tsc checks against the shipped .d.ts/.d.cts files) before running the test matrix, plus a separate CodeQL workflow. Error handling is centralized in lib/misc/errors.js, which raises typed, code-tagged errors (e.g. ER_WRONG_AUTO_TIMEZONE) rather than swallowing failures, and the codebase uses modern private class fields (#idleConnections, #closed) to enforce encapsulation in classes like Pool.
API Design
The public API is intentionally small and symmetrical: createConnection, createPool, createPoolCluster, and importFile cover the vast majority of use cases, with query()/execute()/batch() as the core data methods on a connection. Promise and callback variants are exposed as separate module entry points (mariadb vs mariadb/callback) rather than a single dual-mode API, keeping each surface simple and its TypeScript types unambiguous. Getting started requires no boilerplate beyond createPool(options) plus await pool.getConnection() - documented directly in the README with a complete working example - and connection/pool option objects are validated up front through dedicated ConnectionOptions/PoolOptions classes, which produce clear errors early rather than surfacing failures deep in a query call.
Used by 4 apps in this directory
Bun
Developer Tools
An all-in-one JavaScript and TypeScript toolkit — one Rust-and-JavaScriptCore binary that replaces Node.js, npm, a bundler, and a test runner with faster equivalents.
Dolt
Databases · Data Engineering · Developer Tools
The SQL database you can branch, merge, diff, and clone — Git for your data, MySQL-compatible and ready for multi-agent AI workflows.
NocoBase
No Code Platforms · Low Code Platforms
Open-source AI + no-code platform that lets coding agents and people collaborate to build business systems fast on proven infrastructure.
ToolJet
Low Code Platforms · No Code Platforms · AI Agents
Open-source AI-native platform to build and deploy internal tools, workflows, and AI agents with a visual drag-and-drop builder and 80+ data source integrations.