Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

colin-tech's avatar

Sanctum query

Hi,

I am using laravel sanctum to authenticate my api requests from my standalone frontend. On my frontend, sometimes on mounting the page I need to call a few different endpoints from the server, however with sanctum, it gets the authenticated user via running a db query first select * from "users" where "id" = 1 limit 1. This query is quite slow,(for testing I have 1 user in the table and it takes roughly 500ms to get).

Each endpoint request is doing this, so if I have 3 requests it can take up 1.5 seconds alone which is slow.

Has anyone any advice on how to handle this better or what issues I could be facing? Thanks

0 likes
10 replies
LaryAI's avatar
Level 58

One possible solution to improve the performance of the authentication query in Laravel Sanctum is to cache the authenticated user's data. By caching the user data, subsequent requests can retrieve the user information from the cache instead of querying the database every time.

Here's an example of how you can implement caching in Laravel:

use Illuminate\Support\Facades\Cache;

// ...

$user = Cache::remember('user:' . $userId, $expirationInSeconds, function () use ($userId) {
    return User::find($userId);
});

In this example, we use the Cache::remember method to retrieve the user data from the cache. If the data is not found in the cache, the closure provided as the third argument will be executed to fetch the data from the database and store it in the cache.

You can adjust the $expirationInSeconds parameter to determine how long the user data should be cached before it needs to be refreshed from the database.

By implementing caching, subsequent requests for the same user will retrieve the data from the cache, resulting in improved performance.

Note: Make sure to include the necessary use statements and adjust the code according to your application's specific requirements.

vincent15000's avatar

The Lary's answer is not a good idea : the cache will not change anything and is not secure to check if the user is authenticated.

I don't have this problem and I also use standalone frontend to call APIs in the Laravel backend.

Which frontend are you using ?

colin-tech's avatar

@vincent15000 Was thinking that answer wouldnt help.

I'm using Nuxt 3. I made a composable which uses Nuxt's useFetch, but adds cookies and XSRF-TOKEN to the header

import type { UseFetchOptions } from 'nuxt/app'

export function useApiFetch<T> (path: string, options: UseFetchOptions<T> = {}) {
  let headers: any = {
    accept: "application/json",
    referer: "http://localhost:3000"
  }
  
  const token = useCookie('XSRF-TOKEN')

  if (token.value) {
    headers['X-XSRF-TOKEN'] = token.value as string
  }

  if (process.server){
    headers = {
      ...headers,
      ...useRequestHeaders(["cookie"])
    }
  }

  return useFetch("http://localhost" + path, {
      credentials: "include",
      watch: false,
      ...options,
      headers: {
        ...headers,
        ...options?.headers
      }
  })
}
1 like
vincent15000's avatar

@ColinSWP Sorry I don't use nextjs, so I don't know if the problem comes from nextjs or from another place.

colin-tech's avatar

Thanks Vincent. Im not even sure its my frontend causing it. When you are hitting your laravel api, are you sending the XSRF token and cookies? So that you can access $request->user() ?

1 like
vincent15000's avatar

@ColinSWP When you are using Sanctum, you don't need to add the XSRF token in the query, it's done automatically. But you need to configure properly axios so that it works.

1 like
colin-tech's avatar

@vincent15000 Yeh thats what I do, my fetch includes my 'credientials'. Just seems when I make an authenticated request thats when laravel goes select * from "users" where "id" = 1 LIMIT 1; and causes the slowdown

1 like
gabrieldesousah's avatar

I follow the tutorial from DylanBaine "Scaling Laravel Sanctum" and help me.

Basically, you need to extend the PersonalAccessToken Model in a custom Model and overwrite some functions.

Use of cache isn't a problem if you remove it when needed.

/*
    |--------------------------------------------------------------------------
    | Cache Personal Access Token
    |--------------------------------------------------------------------------
    |
    */
    public static function findToken($token)
    {
        $token = Cache::remember("PersonalAccessToken::$token", 600, function () use ($token) {
            return parent::findToken($token) ?? '_null_';
        });
        if ($token === '_null_') {
            return null;
        }
        return $token;
    }

    public function getTokenableAttribute()
    {
        return Cache::remember("PersonalAccessToken::{$this->id}::tokenable", 600, function () {
            return $this->tokenable()->first();
        });
    }

    public static function boot()
    {
        parent::boot();
        // When updating, cancel normal update and manually update
        // the table asynchronously every hour.
        static::updating(function (self $personalAccessToken) {
            try {
                Cache::remember("PersonalAccessToken::lastUsageUpdate", 3600, function () use ($personalAccessToken) {
                    dispatch(new UpdatePersonalAccessToken($personalAccessToken, $personalAccessToken->getDirty()));
                    return now();
                });
            } catch (Exception $e) {
                logs()->critical($e->getMessage());
            }
            return false;
        });
    }

And create the class UpdatePersonalAccessToken:

class UpdatePersonalAccessToken implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $personalAccessToken;
    protected $newAttributes;

    public function __construct($personalAccessToken, $newAttributes)
    {
        $this->personalAccessToken = $personalAccessToken;
        $this->newAttributes = $newAttributes;
    }

    public function handle()
    {
        DB::table($this->personalAccessToken->getTable())
            ->where('uuid', $this->personalAccessToken->uuid)
            ->update($this->newAttributes);
    }
}
2 likes
vincent15000's avatar

@gabrieldesousah I don't understand why it could be useful to do all this. It's so simple to use Sanctum, you don't have to write such a code.

Please or to participate in this conversation.