Laravel 13.39 writes cache files atomically and adds session cleanup command
Laravel v13.39.0 was published on 27 October with a long list of fixes and a handful of new features, most of them small but aimed at failures that are hard to diagnose in production.
On the operations side, the config, route and event cache files are now written atomically, so a deploy that reads them mid-write no longer sees a half-written file. A new session:garbage-collect command (SessionGarbageCollectCommand) is added and registered. The database cache lock no longer aborts the surrounding transaction on PostgreSQL, a job whose model has been deleted no longer stops queue:retry, and database queue jobs are not failed on concurrency errors while being reserved. Under Octane, the previous route no longer leaks into 404 requests. Filesystem::exists() now blocks the phar:// stream wrapper.
Several fixes target results that were silently wrong: Http::batch() treated failures from retry() and throw() as successes; assertSeeText('0') passed for zero as a string; once() could return a cached value for a different object; pagination counts were wrong for grouped union queries; and the simple paginator ignored a custom page name. JSON:API resource collections with includes lost an N+1 query problem.
New features include disabling the primary key with #[Table(key: false)], a duration on the JobAttempted event, withoutDispatchingAfterResponses on BusFake, and forceCreate and forceCreateQuietly on BelongsToMany.

What it means
The common thread is code that reported success when it had not succeeded — a batch that swallowed failures, a test assertion that passed on the wrong value, a cache file readable half-written. These are the bugs that tests built on the framework inherit without knowing. Teams on 13.x should take this release; anyone relying on Http::batch() results should re-check what their error handling has been seeing.