Session Management

Session Table

Sessions contain id, token, userId, expiresAt, ipAddress, userAgent, createdAt, and updatedAt.

When secondary_storage is configured, Better Auth can store sessions outside the database. Use session.store_session_in_database when you also want a database copy.

Session Expiration

Configure session lifetime with session.expires_in.

auth = BetterAuth.auth(
  secret: ENV.fetch("BETTER_AUTH_SECRET"),
  session: {
    expires_in: 60 * 60 * 24 * 7,
    update_age: 60 * 60 * 24,
    fresh_age: 60 * 5
  }
)

Disable Session Refresh

Pass disableRefresh or disable_refresh to get_session when you do not want the session updatedAt refreshed.

auth.api.get_session(
  headers: {"cookie" => cookie},
  query: {disableRefresh: true}
)

Defer Session Refresh

Ruby refreshes according to update_age. Use disableRefresh for requests that should only read session state.

Session Freshness

Sensitive endpoints require a fresh session. Configure the age window with fresh_age.

session: {
  fresh_age: 60 * 10
}

Endpoints such as password changes, password setting, account unlinking, and user deletion use freshness checks where required.

Session Management

Get Session

auth.api.get_session(headers: {"cookie" => cookie})

Use Session

Rails controllers can use helpers:

class ApplicationController < ActionController::Base
  include BetterAuth::Rails::ControllerHelpers
end

class DashboardController < ApplicationController
  before_action :require_better_auth_session!

  def show
    @session = better_auth_session
    @user = better_auth_user
  end
end

List Sessions

auth.api.list_sessions(headers: {"cookie" => cookie})

Revoke Session

auth.api.revoke_session(
  headers: {"cookie" => cookie},
  body: {token: session_token}
)

Revoke Other Sessions

auth.api.revoke_other_sessions(headers: {"cookie" => cookie})

Revoke All Sessions

auth.api.revoke_sessions(headers: {"cookie" => cookie})

Update Session

Update declared session fields:

auth.api.update_session(
  headers: {"cookie" => cookie},
  body: {activeOrganizationId: "org_123"}
)

The field must exist in session schema or additional fields.

Revoking Sessions On Password Change

auth.api.change_password(
  headers: {"cookie" => cookie},
  body: {
    currentPassword: "old-password",
    newPassword: "new-password",
    revokeOtherSessions: true
  }
)

Session Caching

Enable cookie cache to avoid a database or secondary-storage read on every session lookup.

session: {
  cookie_cache: {
    enabled: true,
    max_age: 60 * 5
  }
}

Use the configured cookie cache strategy for your deployment. The cache stores session/user data in Better Auth cookies and is refreshed as sessions refresh.

Sessions In Secondary Storage

Configure secondary storage to store sessions outside the database.

auth = BetterAuth.auth(
  secret: ENV.fetch("BETTER_AUTH_SECRET"),
  secondary_storage: redis_storage
)

Storing Sessions In The Database

session: {
  store_session_in_database: true
}

Preserving Sessions

session: {
  preserve_session_in_database: true
}

This keeps database session rows after the secondary-storage record is deleted.

Stateless Session Management

Basic Stateless Setup

Use database: nil when your app relies on cookie-backed session state and plugin behavior that does not require persistent adapter writes.

auth = BetterAuth.auth(
  secret: ENV.fetch("BETTER_AUTH_SECRET"),
  database: nil,
  session: {
    cookie_cache: {
      enabled: true
    }
  }
)

Understanding refreshCache

Refresh behavior is controlled by session expiration, update age, and cookie cache settings.

Versioning Stateless Sessions

When rolling out stateless sessions, rotate secrets carefully and keep old secrets configured long enough for existing cookies to expire.

Stateless With Secondary Storage

Secondary storage can be combined with cookie cache to share sessions between processes while reducing database reads.

Customizing Session Response

Use session additional fields or the custom session plugin to shape session data.

auth = BetterAuth.auth(
  secret: ENV.fetch("BETTER_AUTH_SECRET"),
  session: {
    additional_fields: {
      activeOrganizationId: {
        type: "string",
        required: false
      }
    }
  }
)

Caveats On Customizing Session Response

Only expose fields that are safe for clients. Avoid adding secrets, raw provider tokens, password hashes, or internal authorization state to session responses.