---
title: Optimizing for Performance
description: A guide to optimizing your Better Auth application for performance.
---
In this guide, we’ll go over some of the ways you can optimize your application for a more performant Better Auth app.
## Caching
Caching is a powerful technique that can significantly improve the performance of your Better Auth application by reducing the number of database queries and speeding up response times.
### Cookie Cache
Calling your database every time `useSession` or `getSession` is invoked isn’t ideal, especially if sessions don’t change frequently. Cookie caching handles this by storing session data in a short-lived, signed cookie similar to how JWT access tokens are used with refresh tokens.
To turn on cookie caching, just set `session.cookieCache` in your auth config:
```ts title="auth.ts"
import { betterAuth } from "better-auth";
export const auth = betterAuth({
session: {
cookieCache: {
enabled: true,
maxAge: 5 * 60, // Cache duration in seconds
},
},
});
```
Read more about [cookie caching](/docs/concepts/session-management#cookie-cache).
### Framework Caching
Here are examples of how you can do caching in different frameworks and environments:
Since Next v15, we can use the `"use cache"` directive to cache the response of a server function.
```ts
export async function getUsers() {
'use cache' // [!code highlight]
const { users } = await auth.api.listUsers();
return users
}
```
Learn more about NextJS use cache directive here.
In Remix, you can use the `cache` option in the `loader` function to cache responses on the server. Here’s an example:
```ts
import { json } from '@remix-run/node';
export const loader = async () => {
const { users } = await auth.api.listUsers();
return json(users, {
headers: {
'Cache-Control': 'max-age=3600', // Cache for 1 hour
},
});
};
```
You can read a nice guide on Loader vs Route Cache Headers in Remix here.
In SolidStart, you can use the `query` function to cache data. Here’s an example:
```tsx
const getUsers = query(
async () => (await auth.api.listUsers()).users,
"getUsers"
);
```
Learn more about SolidStart `query` function here.
With React Query you can use the `useQuery` hook to cache data. Here’s an example:
```ts
import { useQuery } from '@tanstack/react-query';
const fetchUsers = async () => {
const { users } = await auth.api.listUsers();
return users;
};
export default function Users() {
const { data: users, isLoading } = useQuery('users', fetchUsers, {
staleTime: 1000 * 60 * 15, // Cache for 15 minutes
});
if (isLoading) return
Loading...
;
return (
{users.map(user => (
{user.name}
))}
);
}
```
Learn more about React Query use cache directive here.
## SSR Optimizations
If you're using a framework that supports server-side rendering, it's usually best to pre-fetch the user session on the server and use it as a fallback on the client.
```ts
const session = await auth.api.getSession({
headers: await headers(),
});
//then pass the session to the client
```
## Database optimizations
Optimizing database performance is essential to get the best out of Better Auth.
#### Recommended fields to index
| Table | Fields | Plugin |
| ------------- | -------------------------- | ------------ |
| users | `email` | |
| accounts | `userId` | |
| sessions | `userId`, `token` | |
| verifications | `identifier` | |
| invitations | `email`, `organizationId` | organization |
| members | `userId`, `organizationId` | organization |
| organizations | `slug` | organization |
| passkey | `userId` | passkey |
| twoFactor | `secret` | twoFactor |
We intend to add indexing support in our schema generation tool in the future.