Skip to main content

MySQL Drivers

Drizzle ORM supports MySQL and MySQL-compatible databases through multiple driver implementations.

mysql2

The most popular MySQL driver for Node.js with prepared statement support.

Installation

npm install drizzle-orm mysql2

Basic Usage

import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';

const connection = await mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'mydb',
});

const db = drizzle(connection);

Connection Pool Configuration

import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';

const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'mydb',
  
  // Pool settings
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0,
  enableKeepAlive: true,
  keepAliveInitialDelay: 0,
  
  // Timezone handling
  timezone: '+00:00',
  
  // Charset
  charset: 'utf8mb4',
});

const db = drizzle(pool);

MySQL Modes

Drizzle supports two modes for MySQL connections:
Standard MySQL mode with full feature support including foreign keys and relational queries.
import { drizzle } from 'drizzle-orm/mysql2';
import * as schema from './schema';

const db = drizzle(connection, {
  schema,
  mode: 'default',
});
Use default mode for traditional MySQL and MariaDB databases.

Callback API

mysql2 supports both callback and promise-based APIs. Drizzle handles both:
import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2'; // Note: not mysql2/promise

// Callback-based pool
const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  database: 'mydb',
});

// Drizzle automatically converts to promise-based API
const db = drizzle(pool);

Accessing the Client

const db = drizzle(pool);

// Access underlying mysql2 client
await db.$client.query('SELECT NOW()');

PlanetScale Serverless

Serverless MySQL driver optimized for PlanetScale’s database platform.

Installation

npm install drizzle-orm @planetscale/database

Basic Usage

import { drizzle } from 'drizzle-orm/planetscale-serverless';
import { Client } from '@planetscale/database';

const client = new Client({
  host: process.env.DATABASE_HOST,
  username: process.env.DATABASE_USERNAME,
  password: process.env.DATABASE_PASSWORD,
});

const db = drizzle(client);

Environment Variables

PlanetScale provides connection details in your dashboard:
DATABASE_HOST="aws.connect.psdb.cloud"
DATABASE_USERNAME="username"
DATABASE_PASSWORD="pscale_pw_***"
Or use the connection string format:
DATABASE_URL="mysql://username:pscale_pw_***@aws.connect.psdb.cloud/database?ssl={\"rejectUnauthorized\":true}"

Advanced Configuration

import { drizzle } from 'drizzle-orm/planetscale-serverless';
import { Client } from '@planetscale/database';

const client = new Client({
  host: process.env.DATABASE_HOST,
  username: process.env.DATABASE_USERNAME,
  password: process.env.DATABASE_PASSWORD,
  fetch: (url, init) => {
    // Custom fetch implementation
    return fetch(url, {
      ...init,
      cache: 'no-store',
    });
  },
});

const db = drizzle(client);

Edge Runtime Example

import { drizzle } from 'drizzle-orm/planetscale-serverless';
import { Client } from '@planetscale/database';
import * as schema from './schema';

export const runtime = 'edge';

const client = new Client({
  host: process.env.DATABASE_HOST,
  username: process.env.DATABASE_USERNAME,
  password: process.env.DATABASE_PASSWORD,
});

const db = drizzle(client, { schema });

export async function GET() {
  const users = await db.select().from(schema.users);
  return Response.json(users);
}
PlanetScale doesn’t support foreign key constraints. Use mode: 'planetscale' with mysql2 driver when connecting to PlanetScale via standard MySQL protocol.

Choosing a Driver

Recommended: mysql2
  • Full MySQL/MariaDB feature support
  • Connection pooling
  • Prepared statements
  • Best for long-running Node.js servers
import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';

const pool = mysql.createPool({
  uri: process.env.DATABASE_URL,
  connectionLimit: 10,
});

const db = drizzle(pool, { mode: 'default' });

SSL/TLS Connections

mysql2 with SSL

import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';
import fs from 'fs';

const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'mydb',
  ssl: {
    ca: fs.readFileSync('/path/to/ca.pem'),
    cert: fs.readFileSync('/path/to/client-cert.pem'),
    key: fs.readFileSync('/path/to/client-key.pem'),
  },
});

const db = drizzle(pool);

PlanetScale (SSL Automatic)

PlanetScale connections are automatically encrypted:
import { drizzle } from 'drizzle-orm/planetscale-serverless';
import { Client } from '@planetscale/database';

const client = new Client({
  host: process.env.DATABASE_HOST,
  username: process.env.DATABASE_USERNAME,
  password: process.env.DATABASE_PASSWORD,
  // SSL is enabled by default
});

const db = drizzle(client);

Common Providers

AWS RDS MySQL

import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';

const pool = mysql.createPool({
  host: process.env.RDS_HOSTNAME,
  port: parseInt(process.env.RDS_PORT),
  user: process.env.RDS_USERNAME,
  password: process.env.RDS_PASSWORD,
  database: process.env.RDS_DB_NAME,
  ssl: 'Amazon RDS',
});

const db = drizzle(pool, { mode: 'default' });

Google Cloud SQL

import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';

const pool = mysql.createPool({
  socketPath: `/cloudsql/${process.env.CLOUD_SQL_CONNECTION_NAME}`,
  user: process.env.DB_USER,
  password: process.env.DB_PASS,
  database: process.env.DB_NAME,
});

const db = drizzle(pool, { mode: 'default' });

Railway

import { drizzle } from 'drizzle-orm/mysql2';

// Railway provides MYSQL_URL
const db = drizzle(process.env.MYSQL_URL, {
  mode: 'default',
});

Mock Database for Testing

Both drivers support creating mock instances:
import { drizzle } from 'drizzle-orm/mysql2';
import * as schema from './schema';

const mockDb = drizzle.mock({
  schema,
  mode: 'default',
});
When using schema in configuration, always specify mode: 'default' or mode: 'planetscale'.

Build docs developers (and LLMs) love