View all articles

Laravel: Cache put fails silently with a zero TTL

While testing a job that fetches CPI data and caches the latest index ID, I noticed the cache key was never being set. No error, no warning, just null on retrieval.

Diagnosis

The job logic looked fine:

Cache::put('some_key', $latest->id, $this->secondsUntilMidnight());

The method:

private function secondsUntilMidnight(): int
{
    return now()->diffInSeconds(now()->endOfDay(), false);
}

The problem? That method sometimes returns 0, especially in tests or time-sensitive execution windows. Laravel silently discards the cache if the TTL is 0.

Fix

Ensure a sane minimum TTL:

private function secondsUntilMidnight(): int
{
    return max(now()->diffInSeconds(now()->endOfDay(), false), 60);
}

This guarantees the cache is written, even if the clock’s close to midnight.

Lesson

If you’re caching anything with a dynamic TTL, clamp it. Laravel won’t tell you when it throws the value away.