MySQL

MySQL is supported by the core better_auth gem through the direct MySQL adapter. Rails applications can use better_auth-rails with ActiveRecord on top of MySQL.

Use the lambda form when configuring the direct adapter. Better Auth passes the final configuration into the lambda, so the adapter sees plugins, custom model names, custom field names, and advanced.database.generate_id.

Install Dependencies

Gemfile
gem "better_auth"
gem "mysql2"
Terminal
bundle install

Example Usage

config/auth.rb
require "better_auth"

auth = BetterAuth.auth(
  secret: ENV.fetch("BETTER_AUTH_SECRET"),
  base_url: ENV.fetch("BETTER_AUTH_URL"),
  database: ->(options) {
    BetterAuth::Adapters::MySQL.new(
      options,
      url: ENV.fetch("DATABASE_URL")
    )
  }
)

You may also pass an existing Mysql2::Client when your app owns connection management.

config/auth.rb
require "mysql2"

client = Mysql2::Client.new(
  host: "localhost",
  username: "root",
  password: ENV.fetch("MYSQL_PASSWORD"),
  database: "app_development",
  symbolize_keys: false
)

auth = BetterAuth.auth(
  secret: ENV.fetch("BETTER_AUTH_SECRET"),
  database: ->(options) {
    BetterAuth::Adapters::MySQL.new(
      options,
      connection: client
    )
  }
)

Rails

Rails apps should normally use better_auth-rails and the ActiveRecord adapter.

Gemfile
gem "better_auth-rails"
gem "mysql2"
Terminal
bin/rails generate better_auth:install
bin/rails db:migrate

Schema generation & migration

The Ruby schema helpers generate MySQL DDL from the same Better Auth configuration used at runtime, including plugins, custom model names, custom field names, and additional_fields.

MySQL Schema Generation

MySQL Schema Migration

✅ Supported✅ Supported
db/better_auth_schema.rb
config = BetterAuth::Configuration.new(
  secret: ENV.fetch("BETTER_AUTH_SECRET"),
  database: :memory,
  plugins: []
)

statements = BetterAuth::Schema::SQL.create_statements(
  config,
  dialect: :mysql
)

puts statements.join("\n\n")
db/migrate_better_auth.rb
require "better_auth"
require "mysql2"

config = BetterAuth::Configuration.new(
  secret: ENV.fetch("BETTER_AUTH_SECRET"),
  database: :memory,
  plugins: []
)

statements = BetterAuth::Schema::SQL.create_statements(
  config,
  dialect: :mysql
)

client = Mysql2::Client.new(
  host: "localhost",
  username: "root",
  password: ENV.fetch("MYSQL_PASSWORD"),
  database: "app_development",
  symbolize_keys: false
)
statements.each { |sql| client.query(sql) }

Joins (Experimental)

Enable experimental joins when you want Better Auth to ask the database adapter to fetch related records in one adapter call.

config/auth.rb
auth = BetterAuth.auth(
  secret: ENV.fetch("BETTER_AUTH_SECRET"),
  experimental: { joins: true },
  database: ->(options) {
    BetterAuth::Adapters::MySQL.new(
      options,
      url: ENV.fetch("DATABASE_URL")
    )
  }
)

The MySQL adapter supports native joins for core relationships and for plugin schema relationships declared with references. Rails uses generated ActiveRecord associations for the same schema-driven relationships.

Schema

The Ruby schema maps Better Auth logical fields to MySQL physical columns.

Better Auth fieldMySQL column
emailVerifiedemail_verified
userIduser_id
createdAtcreated_at
expiresAtexpires_at

MySQL DDL uses InnoDB, utf8mb4, json for JSON-like fields, datetime(6) for date fields, and varchar(191) for indexed strings. Ids are generated as hex strings by default. Set advanced: { database: { generate_id: "uuid" } } to generate UUID strings instead.

Additional Information

  • The direct adapter supports the shared Better Auth CRUD contract, where operators, sorting, pagination, counts, transactions, and native joins.
  • If you pass your own Mysql2::Client, configure connection settings such as timezone/session behavior in that client before handing it to Better Auth.
  • Rails apps should prefer Rails migrations generated by better_auth-rails; direct SQL generation is intended for non-Rails apps or custom migration workflows.

On this page