SQLite

SQLite is supported by the core better_auth gem through the sqlite3 gem. It is useful for local development, single-node Rack apps, tests, and small deployments.

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 "sqlite3"
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::SQLite.new(
      options,
      path: "storage/better_auth.sqlite3"
    )
  }
)

You may also pass an existing SQLite3::Database object when your application owns connection lifecycle.

config/auth.rb
require "sqlite3"

database = SQLite3::Database.new("storage/better_auth.sqlite3")
database.results_as_hash = true

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

Rails

Rails apps can use better_auth-rails with ActiveRecord and SQLite.

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

Schema generation & migration

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

SQLite Schema Generation

SQLite 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: :sqlite
)

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

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

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

database = SQLite3::Database.new("storage/better_auth.sqlite3")
statements.each { |sql| database.execute(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::SQLite.new(
      options,
      path: "storage/better_auth.sqlite3"
    )
  }
)

The SQLite 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 adapter stores Better Auth logical fields as snake_case SQLite columns.

Better Auth fieldSQLite column
emailVerifiedemail_verified
userIduser_id
createdAtcreated_at
expiresAtexpires_at

JSON-like fields are stored as JSON text and parsed on output, booleans are stored as integers, and ids are generated as hex strings by default. Set advanced: { database: { generate_id: "uuid" } } to generate UUID strings instead.

Additional Information

  • The direct adapter enables foreign keys with PRAGMA foreign_keys = ON.
  • The direct adapter supports the shared Better Auth CRUD contract, where operators, sorting, pagination, counts, transactions, and native joins.
  • 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