mysql

A pure JavaScript MySQL client for Node.js with connection pooling, streaming, and zero native bindings.

Library
npm
v2.18.1
18,617stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
48/100Fair
Development Activity0
Maintenance0
Community92
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
57/100Fair
Architecture75
Code Quality72
Innovation45
Learning Curve35

mysql is one of the original Node.js drivers for MySQL, implementing the MySQL wire protocol entirely in JavaScript so it installs without compiling native bindings. It exposes callback-based connection, pool, and pool-cluster APIs that support prepared-style placeholder queries, streaming result sets, transactions, and SSL.

The library has been in maintenance mode for years and is widely considered superseded by its successor mysql2 (which adds promises and prepared statements at the protocol level), but it remains deeply embedded in the Node.js ecosystem as the driver behind older Knex, Sequelize, and custom data-access layers still running in production.

What You Get

  • Single connections, connection pools, and pool clusters (for read replicas/failover) from one consistent API
  • Automatic SQL value and identifier escaping via placeholders, plus manual mysql.escape/mysql.format helpers
  • Streaming query results as a Node.js Readable stream for processing large result sets without buffering them in memory
  • Built-in support for transactions, stored procedures, multiple-statement queries, and custom type casting
  • SSL connection profiles (including a built-in Amazon RDS profile) and configurable connection flags

Common Use Cases

  • Connecting a legacy or long-running Node.js service to a MySQL/MariaDB database without adding compiled dependencies
  • Pooling connections behind an Express/Koa API server under concurrent request load
  • Streaming large SELECT results row-by-row for ETL or export jobs instead of loading them all into memory
  • Routing reads across multiple MySQL replicas with automatic failover via PoolCluster

Under The Hood

Architecture The codebase separates connection management from wire-protocol handling: Connection.js, Pool.js, and PoolCluster.js provide the public, callback/EventEmitter-based API, while lib/protocol/Protocol.js drives a queue of protocol “sequences” (Handshake, Auth, Query, ChangeUser, Ping, Quit under lib/protocol/sequences/) that each model one exchange of the MySQL binary protocol, encoded and decoded via Parser.js, PacketWriter.js, and BufferList.js. A call to connection.query() is turned into a Query sequence by Connection.createQuery, enqueued on the shared Protocol instance, and its results are streamed back through callbacks or query events — every higher-level class (Connection, Pool, PoolCluster) depends on this single protocol dispatch loop, so it is the one abstraction the rest of the library cannot function without.

Tech Stack The library targets plain Node.js (engines allows down to 0.6) with zero native bindings, implementing the MySQL protocol entirely in JavaScript. Its only runtime dependencies are narrowly scoped: bignumber.js for precise BIGINT/DECIMAL handling, readable-stream for a consistent Streams API across old Node versions, safe-buffer for safe buffer allocation, and sqlstring (a sibling project) for SQL escaping/formatting. There is no build step, bundler, or TypeScript — it ships as CommonJS, and its CI matrix (GitHub Actions ci.yml) still tests against Node 0.6 through 12.x and multiple io.js releases, reflecting a strong backward-compatibility priority over adopting newer language features.

Code Quality Tests live under test/unit and test/integration using the project’s own minimal utest/urun test runner rather than a mainstream framework, with plain assert calls covering ConnectionConfig, PoolConfig, protocol packets, and query sequences in reasonable depth. Errors are modeled explicitly with .code and .fatal properties so fatal connection errors can be distinguished from recoverable query errors, and ESLint (.eslintrc) is enforced in CI alongside the full version matrix. There are no TypeScript types in the source itself (consumers rely on separately maintained @types/mysql definitions), and the callback-first style means no first-class async/await support without wrapping.

API Design Getting started takes only a few lines — createConnection, .connect(), .query() — and the placeholder-based ?/named-object query interface keeps escaping automatic by default. The trade-off is a callback-only public surface: there is no built-in Promise or async/await API, so modern codebases typically wrap calls with util.promisify or reach for a promise-native fork instead. Documentation is unusually thorough for a driver of this age, with a long, example-heavy README covering SSL profiles, custom type casting, and pool-cluster configuration in detail.

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