La regla: cachea lo que es lento, no lo que es cómodo de cachear. Una búsqueda local de Eloquent por clave primaria ya es rápida. Cachearla no te ahorra nada y añade una clase de error (lecturas rancias) que antes no tenías.
La búsqueda del token Bearer delante de cada petición sí es genuinamente cara si no la cacheas: EnsureTokenIsValidMiddleware corre antes de que la petición llegue a un controlador y, sin ayuda, eso significa una consulta a base de datos en cada llamada autenticada.
use CachesBearerTokens: un trait compartido, no un método local. Todos los servicios que autentican un token Bearer usan la misma lógica de caché en lugar de cinco copias ligeramente distintas separándose con el tiempo.
rememberBearerToken(): mira primero la caché y sólo consulta la base de datos si falla. La misma forma que Cache::remember, sólo que envuelta para que la decisión caché-o-base-de-datos no se repita en cada punto de llamada.
El TTL no es un número plano. Cuando el token lleva expiración, la duración se calcula desde ese expires_at menos un margen de cinco minutos, no una hora fija, así que un token cacheado no puede sobrevivir de forma relevante al registro del que se cacheó. Un TTL plano de «cachea todo una hora» dejaría que un token expirado o revocado siguiera autenticando hasta una hora después de que debiera haber dejado de funcionar. Eso no es un problema de rendimiento: es un problema de seguridad disfrazado de rendimiento.
La prueba no es «¿puedo cachear esto?». Es «¿notaría si esta llamada desapareciera durante lo que dura el TTL?». Una búsqueda por clave primaria, no. Un golpe a la base de datos en cada petición autenticada de toda la flota, sí.
Invalidacion de caches sobre la que puedas razonar
Cachear es fácil. Saber cuándo tirar la caché es el problema de verdad, y es la razón de que «cachéalo y ya» sea un mal consejo por sí solo.
La convención de la flota es aburrida a propósito: cada sitio que escribe datos sabe exactamente qué clave de caché invalida esa escritura, y llama a Cache::forget() sobre ella directamente. Sin etiquetas, sin borrados con comodines, sin bus de eventos de invalidación.
// app/Services/DependencyHealth.php
public function recordSuccess(Dependency $dependency): void
{
Cache::forget($this->downKey($dependency));
Cache::forget($this->failKey($dependency));
}
public function recordFailure(Dependency $dependency): void
{
$key = $this->failKey($dependency);
$failures = Cache::add($key, 1, now()->addSeconds(self::$windowSeconds))
? 1
: (int) Cache::increment($key);
if ($failures >= self::$failureThreshold) {
$this->markDown($dependency);
Cache::forget($key);
}
}
La escritura y la invalidación viven en la misma clase, a pocas líneas de distancia, nombrando las claves exactas. Dentro de seis meses, quien lea recordFailure() verá la historia completa sin ir a buscar dónde más se tocan esas claves.
Compáralo con un ayudante genérico de «limpia las cachés relacionadas» que se despliega hacia claves que no nombra. Parece más sofisticado. También es lo que nadie sabe explicar en mitad de un incidente: ¿qué cachés limpia esto exactamente? Una clave de caché que no puedes rastrear hasta la escritura que debería limpiarla es una clave en la que no puedes confiar. Nombra la clave, olvídala en el sitio de la escritura, listo.