How to Connect to MariaDB from Rust

6 min readMariaDB

There is no MariaDB-specific Rust driver, and you do not need one. MariaDB speaks the MySQL wire protocol, so the same crates that connect to MySQL connect to MariaDB: mysql (sync), mysql_async (tokio), and sqlx. If you have read our MySQL from Rust guide, everything there applies here.

This guide covers what actually differs. Two things are genuinely MariaDB-specific from Rust's point of view: the ed25519 and PARSEC authentication plugins -- where crate support varies in ways that produce confusing failures -- and INSERT ... RETURNING.

The options

LibraryModelMariaDB ed25519 authVersion (as of July 2026)
mysqlSync driver, pure Rust, pool includedYes, behind the client_ed25519 feature28.0.0
mysql_asyncAsync driver (tokio), pure Rust, pool includedYes, behind the client_ed25519 feature0.37.0
sqlxAsync toolkit, compile-time checked SQLNo0.9.0
DieselSync ORM, binds to the C client libraryDepends on the installed client library2.3.11

Connecting

The URL scheme is mysql:// regardless of which server is on the other end -- there is no mariadb:// scheme in these crates:

[dependencies]
mysql = "28"
use mysql::*;
use mysql::prelude::*;
 
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let url = "mysql://app:secret@localhost:3306/mydb";
    let pool = Pool::new(url)?;
    let mut conn = pool.get_conn()?;
 
    let version: String = conn.query_first("SELECT VERSION()")?.unwrap();
    println!("{version}"); // e.g. 11.8.3-MariaDB
    Ok(())
}

The async variant is the same shape with mysql_async::Pool and .await. Both dedicated drivers ship a built-in connection pool -- no separate pooling crate needed. Prepared statements use ? positional placeholders; named parameters (:name) are translated client-side by the driver, so a literal :something inside a string in your SQL can be misparsed -- the same quirk as with MySQL.

As with MySQL, use utf8mb4. MariaDB's utf8 is the legacy 3-byte alias (utf8mb3); emoji and supplementary-plane characters need utf8mb4 tables and connections.

Authentication: where MariaDB actually differs

MariaDB does not use caching_sha2_password, MySQL 8's default plugin. Standard MariaDB password accounts use mysql_native_password, which every Rust crate supports out of the box. So the MySQL 8 auth headache is absent -- but MariaDB has two plugins of its own.

ed25519

MariaDB's ed25519 plugin replaces SHA-1 password hashing with an elliptic-curve signature scheme. Accounts created with IDENTIFIED VIA ed25519 fail against clients that don't implement it -- with correct credentials. In several language ecosystems (Ruby, PHP) no driver implements it at all.

Rust is better off: mysql and mysql_async both support it, but only behind a feature flag, because it pulls in extra cryptography dependencies:

[dependencies]
mysql = { version = "28", features = ["client_ed25519"] }
# or
mysql_async = { version = "0.37", features = ["client_ed25519"] }

Without the feature, connecting to an ed25519 account fails with an "unknown authentication plugin" error even though the password is right. Enable the feature; don't downgrade the account.

sqlx does not implement ed25519 (its MySQL auth covers mysql_native_password, caching_sha2_password, and sha256_password). If your MariaDB accounts use ed25519, sqlx cannot log in -- switch the account to mysql_native_password or use one of blackbeam's drivers.

PARSEC (MariaDB 11.6+)

MariaDB 11.6 introduced PARSEC (PBKDF2 plus an ed25519 signature), which MariaDB intends to make the default plugin in a future release. Same story: mysql and mysql_async support it behind the client_parsec feature; sqlx does not. If you run MariaDB 11.6+ and a future upgrade flips the default, this feature flag is the difference between a working deployment and an authentication mystery.

INSERT ... RETURNING

Since MariaDB 10.5, INSERT ... RETURNING (and DELETE ... RETURNING) returns rows from the statement -- something MySQL still doesn't have. From Rust this is just a query that returns rows, so use the query API, not the exec API:

let id: Option<u64> = conn.query_first(
    "INSERT INTO users (email) VALUES ('a@example.com') RETURNING id",
)?;

The portable alternative is last_insert_id(), available on the connection after an exec:

conn.exec_drop("INSERT INTO users (email) VALUES (?)", ("a@example.com",))?;
let id = conn.last_insert_id();

RETURNING is the better tool when you insert multiple rows (per-row ids, not just the first) or need non-key columns back. Just remember it ties you to MariaDB -- the same statement fails on MySQL with a syntax error.

sqlx with MariaDB

sqlx officially supports MariaDB through its MySQL driver, and its CI tests against MariaDB versions. Everything from the MySQL guide applies -- MySqlPoolOptions, compile-time checked query! macros, the works:

use sqlx::mysql::MySqlPoolOptions;
 
let pool = MySqlPoolOptions::new()
    .max_connections(10)
    .connect("mysql://app:secret@localhost:3306/mydb")
    .await?;

The two caveats: the auth plugin gap above, and that query!'s compile-time verification runs against whatever server DATABASE_URL points at -- point it at MariaDB, not MySQL, or the macros will happily verify SQL that only works on the other server (in either direction).

TLS

Both blackbeam drivers offer native-tls and rustls feature flags; sqlx selects TLS via feature flags (tls-rustls-ring-webpki, tls-native-tls) and ?ssl-mode= in the URL. Verify the server certificate in production (SslOpts with a CA in mysql/mysql_async, ssl-mode=VERIFY_IDENTITY in sqlx); skipping verification protects against passive snooping only.

Common mistakes

MistakeSymptomFix
ed25519 account, feature flag missingAuth fails with correct credentials, "unknown plugin"features = ["client_ed25519"] on mysql/mysql_async
ed25519 or PARSEC account with sqlxLogin fails, no feature flag can fix itUse mysql_native_password for that account, or switch driver
Expecting caching_sha2_password issuesCargo-culted MySQL 8 workarounds that do nothingMariaDB standard accounts are mysql_native_password -- plain connections just work
Legacy utf8 charsetEmoji and 4-byte characters rejected or mangledutf8mb4 tables and connection charset
RETURNING in portable codeSyntax error on MySQLGate it to MariaDB 10.5+, or use last_insert_id()
sqlx macros verified against MySQLCompile-time pass, runtime failure on MariaDB (or vice versa)Point DATABASE_URL at the server you deploy on

Once your Rust service is writing to MariaDB, you still need to look at the data. Mako connects to MariaDB alongside PostgreSQL, MySQL, and the rest, with AI-powered autocomplete for exploring schemas you didn't design. Try it free at mako.ai.

Mako — open source

Skip the terminal. Use Mako.

Connect your database, write queries with AI assistance, and import/export data in clicks. Free to start.