Connect to MySQL
Tested with: MySQL 8.4.6 on Databasezy (Percona Operator) · drivers listed per tab · zb CLI 0.1
- Copy the host and port from the instance’s Connect tab. Credentials were shown once at creation.
- Download the CA bundle (
zb api GET /v1/orgs/{org}/ca.pem > databasezy-ca.pem). The MySQL protocol sends the server greeting before TLS, so the gateway cannot fall back to a public certificate for clients that skip verification: always pass the CA and ask for identity verification. - Add your egress IPs under Network → Allow-list.
- Use a snippet below. Each one sets
VERIFY_IDENTITY(chain and hostname) or the driver’s equivalent.
MySQL listens on port 3306 (MySQL wire protocol). Versions: 8.4, 8.0. Replace the example host with the one on your instance's Connect tab; credentials are shown once at creation.
mysql://app:<password>@mysql-7f3k.us-east.databasezy.com:3306/app?ssl-mode=VERIFY_IDENTITY&ssl-ca=databasezy-ca.pemimport { readFileSync } from "node:fs";import mysql from "mysql2/promise";
export const pool = mysql.createPool({ host: "mysql-7f3k.us-east.databasezy.com", port: 3306, user: "app", password: process.env.ZB_PASSWORD, database: "app", ssl: { ca: readFileSync("databasezy-ca.pem", "utf8"), rejectUnauthorized: true, // verify chain and hostname }, connectionLimit: 10,});
const [rows] = await pool.query("select version() as v");console.log(rows[0].v);Tested with: MySQL 8.4 · mysql2 3.11
import osimport pymysql
conn = pymysql.connect( host="mysql-7f3k.us-east.databasezy.com", port=3306, user="app", password=os.environ["ZB_PASSWORD"], database="app", ssl={"ca": "databasezy-ca.pem"}, ssl_verify_cert=True, ssl_verify_identity=True, # hostname check)with conn.cursor() as cur: cur.execute("select version()") print(cur.fetchone())Tested with: MySQL 8.4 · PyMySQL 1.1
package main
import ( "crypto/tls" "crypto/x509" "database/sql" "fmt" "os"
"github.com/go-sql-driver/mysql")
func main() { pem, err := os.ReadFile("databasezy-ca.pem") if err != nil { panic(err) } roots := x509.NewCertPool() roots.AppendCertsFromPEM(pem) mysql.RegisterTLSConfig("databasezy", &tls.Config{ RootCAs: roots, ServerName: "mysql-7f3k.us-east.databasezy.com", // hostname verification MinVersion: tls.VersionTLS12, })
dsn := fmt.Sprintf("app:%s@tcp(mysql-7f3k.us-east.databasezy.com:3306)/app?tls=databasezy&parseTime=true", os.Getenv("ZB_PASSWORD")) db, err := sql.Open("mysql", dsn) if err != nil { panic(err) } db.SetMaxOpenConns(10) var v string if err := db.QueryRow("select version()").Scan(&v); err != nil { panic(err) } fmt.Println(v)}Tested with: MySQL 8.4 · go-sql-driver/mysql 1.8
use sqlx::mysql::{MySqlConnectOptions, MySqlPoolOptions, MySqlSslMode};
#[tokio::main]async fn main() -> Result<(), sqlx::Error> { let opts = MySqlConnectOptions::new() .host("mysql-7f3k.us-east.databasezy.com") .port(3306) .database("app") .username("app") .password(&std::env::var("ZB_PASSWORD").expect("ZB_PASSWORD")) .ssl_mode(MySqlSslMode::VerifyIdentity) .ssl_ca("databasezy-ca.pem");
let pool = MySqlPoolOptions::new().max_connections(10).connect_with(opts).await?; let (v,): (String,) = sqlx::query_as("select version()").fetch_one(&pool).await?; println!("{v}"); Ok(())}Tested with: MySQL 8.4 · sqlx 0.8 (mysql, tls-rustls)
// One-time: import the CA into a PKCS12 truststore// keytool -importcert -noprompt -alias databasezy -file databasezy-ca.pem \// -keystore databasezy-truststore.p12 -storetype PKCS12 -storepass changeitimport com.zaxxer.hikari.HikariConfig;import com.zaxxer.hikari.HikariDataSource;
public final class Db { public static HikariDataSource open() { var cfg = new HikariConfig(); cfg.setJdbcUrl("jdbc:mysql://mysql-7f3k.us-east.databasezy.com:3306/app" + "?sslMode=VERIFY_IDENTITY" + "&trustCertificateKeyStoreUrl=file:databasezy-truststore.p12" + "&trustCertificateKeyStoreType=PKCS12" + "&trustCertificateKeyStorePassword=changeit"); cfg.setUsername("app"); cfg.setPassword(System.getenv("ZB_PASSWORD")); cfg.setMaximumPoolSize(10); return new HikariDataSource(cfg); }}Tested with: MySQL 8.4 · MySQL Connector/J 9.1 · HikariCP 6.2
using MySqlConnector;
var cs = new MySqlConnectionStringBuilder{ Server = "mysql-7f3k.us-east.databasezy.com", Port = 3306, Database = "app", UserID = "app", Password = Environment.GetEnvironmentVariable("ZB_PASSWORD"), SslMode = MySqlSslMode.VerifyFull, SslCa = "databasezy-ca.pem", MaximumPoolSize = 10,};await using var conn = new MySqlConnection(cs.ConnectionString);await conn.OpenAsync();await using var cmd = new MySqlCommand("select version()", conn);Console.WriteLine(await cmd.ExecuteScalarAsync());Tested with: MySQL 8.4 · MySqlConnector 2.4
<?php$pdo = new PDO("mysql:host=mysql-7f3k.us-east.databasezy.com;port=3306;dbname=app;charset=utf8mb4", "app", getenv("ZB_PASSWORD"), [ PDO::MYSQL_ATTR_SSL_CA => "databasezy-ca.pem", PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,]);echo $pdo->query("select version()")->fetchColumn();Tested with: MySQL 8.4 · PHP 8.3 · PDO mysql (mysqlnd)
require "mysql2"
client = Mysql2::Client.new( host: "mysql-7f3k.us-east.databasezy.com", port: 3306, username: "app", password: ENV.fetch("ZB_PASSWORD"), database: "app", sslca: "databasezy-ca.pem", sslverify: true, # verify chain and hostname ssl_mode: :verify_identity)puts client.query("select version() as v").first["v"]Tested with: MySQL 8.4 · mysql2 0.5 · Ruby 3.3
mysql --host mysql-7f3k.us-east.databasezy.com --port 3306 --user app --password \ --ssl-mode=VERIFY_IDENTITY --ssl-ca=databasezy-ca.pem --tls-sni-servername=mysql-7f3k.us-east.databasezy.com app
# orzb connect mysql-7f3kTested with: MySQL 8.4 · mysql 8.4 client
- Clients must use
--ssl-mode=REQUIREDor stricter;VERIFY_IDENTITYis what the snippets use. - MySQL 8.4 defaults to
caching_sha2_password, which needs TLS or the server public key; on Databasezy TLS is always on so no extra flag is needed. - Java needs the CA in a PKCS12 truststore; the one-line
keytoolimport is in the Java tab.
Pooling
Section titled “Pooling”max_connectionscomes from the size; leave headroom for replication and the backup agent (about 10 connections).- MySQL has no transaction-mode pooler on Databasezy yet; use your driver’s pool (
connectionLimit, HikariCP,SetMaxOpenConns) and keep connections alive with a validation query. - Set
wait_timeoutawareness in your pool: the server closes idle sessions after 8 hours; pools should validate on borrow.
IP allow-list
Section titled “IP allow-list”Enforced at the gateway on every plan. Replication users and the migration agent connect from inside the cell and are not subject to the list.