How to Connect to MariaDB from Ruby

7 min readMariaDB

There is no MariaDB-specific Ruby driver, and you do not need one. MariaDB speaks the MySQL wire protocol, so the same Ruby drivers that connect to MySQL connect to MariaDB: mysql2 and trilogy. This guide shows both, plus Sequel and ActiveRecord on top, and focuses on the two things that actually differ between MariaDB and MySQL from Ruby's point of view: the ed25519 authentication plugin, and INSERT ... RETURNING.

The options

LibraryNative dependencyNotesVersion (as of July 2026)
mysql2libmysqlclient / libmariadbMature, widely deployed default0.5.7
trilogyNone (pure protocol implementation)No client lib to build; Rails-native adapter2.12.6
Sequelvia mysql2 or trilogyToolkit/ORM, uses a driver underneath5.106.0
ActiveRecordvia mysql2 or trilogyFull ORM (Rails)ships with Rails 8.1.3

The practical decision is the same as for MySQL:

  • mysql2 if you want the established option and don't mind installing client libraries at build time. Installing the MariaDB client library (libmariadb-dev) satisfies its dependency perfectly well.
  • trilogy if you want to avoid the C client build dependency (a frequent source of CI and Docker friction) or you are on a recent Rails and want the natively supported adapter.

Installing mysql2 against MariaDB

The gem compiles against a MySQL-compatible client library. The MariaDB Connector/C works and is often the cleaner install on modern systems:

  • Debian/Ubuntu: sudo apt-get install libmariadb-dev
  • macOS (Homebrew): brew install mariadb-connector-c
  • RHEL/Fedora: sudo dnf install MariaDB-shared MariaDB-devel
gem install mysql2

If the build cannot find the client headers, the dev package is missing. trilogy skips this entirely because it implements the protocol in Ruby with no C client to link against.

A minimal connection with mysql2

require 'mysql2'
 
client = Mysql2::Client.new(
  host:     'localhost',
  port:     3306,
  username: 'app',
  password: ENV['DB_PASSWORD'],
  database: 'shop',
  encoding: 'utf8mb4'
)
 
client.query('SELECT VERSION()').each do |row|
  puts row['VERSION()']   # e.g. "11.4.2-MariaDB"
end
 
client.close

The utf8mb4 trap

This applies to MariaDB exactly as it does to MySQL. In this ecosystem utf8 is a historical alias for a 3-byte encoding that cannot store 4-byte characters (emoji, some CJK characters, many symbols). Set utf8mb4 everywhere: in the driver connection (encoding: 'utf8mb4'), and on the database, tables, and columns. Mismatched charsets produce Incorrect string value errors on insert, or silent data loss on older configurations. Use utf8mb4 end to end and the problem disappears.

The ed25519 authentication gotcha (this is the MariaDB-specific one)

Here is the genuine MariaDB difference. MariaDB does not use MySQL 8's caching_sha2_password plugin, so the whole "Authentication plugin caching_sha2_password cannot be loaded" / Public Key Retrieval headache from MySQL 8 simply does not exist here. Good news.

The flip side: MariaDB has its own modern authentication plugin, ed25519, which many MariaDB deployments now use for accounts instead of the legacy mysql_native_password. And the Ruby drivers do not implement the client side of ed25519. If your account was created with:

CREATE USER 'app'@'%' IDENTIFIED VIA ed25519 USING PASSWORD('secret');

then a mysql2 or trilogy connection will fail with a "plugin ... could not be loaded" or authentication error, because the driver cannot answer the ed25519 challenge. This is the failure mode that surprises people moving from MySQL: the driver is fine, the credentials are correct, but the auth plugin is one Ruby's clients don't speak.

Your options:

  • Use a mysql_native_password account for the Ruby app. Create or alter the service account to use native password auth: ALTER USER 'app'@'%' IDENTIFIED VIA mysql_native_password USING PASSWORD('secret');. This is the pragmatic path today.
  • Build mysql2 against a MariaDB Connector/C that has the ed25519 client plugin available, and ensure the plugin .so is discoverable. This works with the C client but adds deployment complexity, and trilogy (pure Ruby) still cannot do it.

If a MariaDB connection that has correct credentials keeps failing, check the account's plugin with SELECT user, plugin FROM mysql.user WHERE user='app'; before assuming a network or password problem.

Parameterized queries and prepared statements

Use bound parameters rather than interpolating into SQL:

stmt = client.prepare('SELECT name, plan FROM accounts WHERE region = ? AND active = ?')
result = stmt.execute('EMEA', true)
result.each { |row| puts "#{row['name']}: #{row['plan']}" }

mysql2 uses ? positional placeholders in prepared statements.

INSERT ... RETURNING (a real MariaDB advantage)

MariaDB supports INSERT ... RETURNING (since 10.5), which MySQL does not. Instead of inserting and then reading last_id, you can get generated values back in one round trip:

row = client.query(
  "INSERT INTO accounts (name, region) VALUES ('Acme', 'EMEA') RETURNING id, created_at"
).first
 
puts row['id']
puts row['created_at']

This is portable across MariaDB but not to MySQL, so if the same code must run against both, fall back to client.last_id after the insert instead.

Connection pooling

Neither mysql2 nor trilogy pools connections on its own. A Mysql2::Client is a single connection and is not thread-safe for concurrent queries. In a threaded server, use the connection_pool gem:

require 'connection_pool'
require 'mysql2'
 
POOL = ConnectionPool.new(size: 5, timeout: 5) do
  Mysql2::Client.new(
    host: 'localhost', username: 'app',
    password: ENV['DB_PASSWORD'], database: 'shop',
    encoding: 'utf8mb4'
  )
end
 
POOL.with do |client|
  client.query('SELECT count(*) AS n FROM accounts').first['n']
end

Size the pool so that pool_size × process_count stays under the server's max_connections (151 by default on MariaDB). For heavy connection churn, a proxy like MaxScale or ProxySQL in front of MariaDB does real connection pooling server-side.

Sequel and ActiveRecord

Sequel picks the driver from the URL scheme:

require 'sequel'
 
# mysql2 driver against MariaDB
DB = Sequel.connect('mysql2://app:secret@localhost/shop?encoding=utf8mb4', max_connections: 5)
# or trilogy
# DB = Sequel.connect('trilogy://app:secret@localhost/shop')
 
DB[:customers].where(region: 'EMEA').each { |row| puts row[:name] }

In Rails, config/database.yml selects the adapter. There is no separate MariaDB adapter; use mysql2 or trilogy:

production:
  adapter: mysql2        # or: trilogy
  host: <%= ENV['DB_HOST'] %>
  database: shop
  username: app
  password: <%= ENV['DB_PASSWORD'] %>
  encoding: utf8mb4
  pool: 5

TLS connections

To require an encrypted connection and verify the server certificate:

client = Mysql2::Client.new(
  host: 'db.internal', username: 'app', password: ENV['DB_PASSWORD'],
  database: 'shop', encoding: 'utf8mb4',
  sslca: '/etc/ssl/certs/ca.pem',
  sslverify: true
)

Setting sslca with verification is the meaningful step; enabling TLS without verifying the certificate protects against passive sniffing but not an active man-in-the-middle.

Common errors

ErrorCause
Cannot find client headers at installMariaDB/MySQL client dev package missing (mysql2 only; trilogy avoids this)
Can't connect to MySQL serverWrong host/port, or server not listening on TCP
Access denied for userWrong credentials, or host-pattern account mismatch
Auth plugin could not be loaded / auth fails with correct passwordAccount uses MariaDB ed25519, which the Ruby drivers can't answer; switch the account to mysql_native_password
Incorrect string value4-byte character into a utf8 (3-byte) column; use utf8mb4 end to end
Too many connectionsPool size × process count exceeds max_connections (151 default)

Querying without writing connection code

If your goal is to explore a MariaDB database rather than build a service, a GUI client skips all of the above. Mako connects to MariaDB with AI-assisted SQL -- see our MariaDB GUI client guide. Connecting from another language? See How to Connect to MariaDB from Python and from Node.js.

Mako connects to MariaDB with AI-powered autocomplete. 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.