Create a Database Adapter
Learn how to create a custom database adapter for Better-Auth using createAdapter.
Our createAdapter function is designed to be very flexible, and we've done our best to make it easy to understand and use.
Our hope is to allow you to focus on writing database logic, and not have to worry about how the adapter is working with Better-Auth.
Anything from custom schema configurations, custom ID generation, safe JSON parsing, and more is handled by the createAdapter function.
All you need to do is provide the database logic, and the createAdapter function will handle the rest.
Quick Start
Get things ready
- Import
createAdapter. - Create
CustomAdapterConfiginterface that represents your adapter config options. - Create the adapter!
Configure the adapter
The config object is mostly used to provide information about the adapter to Better-Auth.
We try to minimize the amount of code you need to write in your adapter functions, and these config options are used to help us do that.
Create the adapter
The adapter function is where you write the code that interacts with your database.
Learn more about the adapter here here.
Adapter
The adapter function is where you write the code that interacts with your database.
If you haven't already, check out the options object in the config section, as it can be useful for your adapter.
Before we get into the adapter function, let's go over the parameters that are available to you.
options: The Better Auth options.schema: The schema from the user's Better Auth instance.debugLog: The debug log function.getField: The get field function.getDefaultModelName: The get default model name function.getDefaultFieldName: The get default field name function.getFieldAttributes: The get field attributes function.
Adapter Methods
- All
modelvalues are already transformed into the correct model name for the database based on the end-user's schema configuration.- This also means that if you need access to the
schemaversion of a given model, you can't use this exactmodelvalue, you'll need to use thegetDefaultModelNamefunction provided in the options to convert themodelto theschemaversion.
- This also means that if you need access to the
- We will automatically fill in any missing fields you return based on the user's
schemaconfiguration. - Any method that includes a
selectparameter, is only for the purpose of getting data from your database more efficiently. You do not need to worry about only returning what theselectparameter states, as we will handle that for you.
create method
The create method is used to create a new record in the database.
Note:
If the user has enabled the useNumberId option, or if generateId is false in the user's Better Auth config,
then it's expected that the id is provided in the data object. Otherwise, the id will be automatically generated.
Additionally, it's possible to pass forceAllowId as a parameter to the create method, which allows id to be provided in the data object.
We handle forceAllowId internally, so you don't need to worry about it.
parameters:
model: The model/table name that new data will be inserted into.data: The data to insert into the database.select: An array of fields to return from the database.
Make sure to return the data that is inserted into the database.
update method
The update method is used to update a record in the database.
parameters:
model: The model/table name that the record will be updated in.where: Thewhereclause to update the record by.update: The data to update the record with.
Make sure to return the data in the row which is updated. This includes any fields that were not updated.
updateMany method
The updateMany method is used to update multiple records in the database.
parameters:
model: The model/table name that the records will be updated in.where: Thewhereclause to update the records by.update: The data to update the records with.
delete method
The delete method is used to delete a record from the database.
parameters:
model: The model/table name that the record will be deleted from.where: Thewhereclause to delete the record by.
deleteMany method
The deleteMany method is used to delete multiple records from the database.
parameters:
model: The model/table name that the records will be deleted from.where: Thewhereclause to delete the records by.
findOne method
The findOne method is used to find a single record in the database.
parameters:
model: The model/table name that the record will be found in.where: Thewhereclause to find the record by.select: Theselectclause to return.
findMany method
The findMany method is used to find multiple records in the database.
parameters:
model: The model/table name that the records will be found in.where: Thewhereclause to find the records by.limit: The limit of records to return.sortBy: ThesortByclause to sort the records by.offset: The offset of records to return.
Make sure to return the array of data that is found in the database.
count method
The count method is used to count the number of records in the database.
parameters:
model: The model/table name that the records will be counted in.where: Thewhereclause to count the records by.
options (optional)
The options object is for any potential config that you got from your custom adapter options.
createSchema (optional)
The createSchema method allows the Better Auth CLI to generate a schema for the database.
parameters:
tables: The tables from the user's Better-Auth instance schema; which is expected to be generated into the schema file.file: The file the user may have passed in to thegeneratecommand as the expected schema file output path.
Test your adapter
We've provided a test suite that you can use to test your adapter. It requires you to use vitest.
Numeric ID tests
If your database supports numeric IDs, then you should run this test as well:
Config
The config object is used to provide information about the adapter to Better-Auth.
We highly recommend going through and reading each provided option below, as it will help you understand how to properly configure your adapter.
Required Config
adapterId
A unique identifier for the adapter.
adapterName
The name of the adapter.
Optional Config
supportsNumericIds
Whether the database supports numeric IDs. If this is set to false and the user's config has enabled useNumberId, then we will throw an error.
supportsJSON
Whether the database supports JSON. If the database doesn't support JSON, we will use a string to save the JSON data.And when we retrieve the data, we will safely parse the string back into a JSON object.
supportsDates
Whether the database supports dates. If the database doesn't support dates, we will use a string to save the date. (ISO string) When we retrieve the data, we will safely parse the string back into a Date object.
supportsBooleans
Whether the database supports booleans. If the database doesn't support booleans, we will use a 0 or 1 to save the boolean value. When we retrieve the data, we will safely parse the 0 or 1 back into a boolean value.
usePlural
Whether the table names in the schema are plural. This is often defined by the user, and passed down through your custom adapter options. If you do not intend to allow the user to customize the table names, you can ignore this option, or set this to false.
debugLogs
Used to enable debug logs for the adapter. You can pass in a boolean, or an object with the following keys: create, update, updateMany, findOne, findMany, delete, deleteMany, count.
If any of the keys are true, the debug logs will be enabled for that method.
disableIdGeneration
Whether to disable ID generation. If this is set to true, then the user's generateId option will be ignored.
customIdGenerator
If your database only supports a specific custom ID generation, then you can use this option to generate your own IDs.
mapKeysTransformInput
If your database uses a different key name for a given situation, you can use this option to map the keys. This is useful for databases that expect a different key name for a given situation.
For example, MongoDB uses _id while in Better-Auth we use id.
Each key in the returned object represents the old key to replace. The value represents the new key.
This can be a partial object that only transforms some keys.
mapKeysTransformOutput
If your database uses a different key name for a given situation, you can use this option to map the keys. This is useful for databases that use a different key name for a given situation.
For example, MongoDB uses _id while in Better-Auth we use id.
Each key in the returned object represents the old key to replace. The value represents the new key.
This can be a partial object that only transforms some keys.
customTransformInput
If you need to transform the input data before it is saved to the database, you can use this option to transform the data.
If you're using supportsJSON, supportsDates, or supportsBooleans, then
the transformations will be applied before your customTransformInput
function is called.
The customTransformInput function receives the following arguments:
data: The data to transform.field: The field that is being transformed.fieldAttributes: The field attributes of the field that is being transformed.select: Theselectvalues which the query expects to return.model: The model that is being transformed.schema: The schema that is being transformed.options: Better Auth options.
The customTransformInput function runs at every key in the data object of a given action.
customTransformOutput
If you need to transform the output data before it is returned to the user, you can use this option to transform the data. The customTransformOutput function is used to transform the output data.
Similar to the customTransformInput function, it runs at every key in the data object of a given action, but it runs after the data is retrieved from the database.