Laravel 13.20 release notes cover listing first-party image processing, queue hooks and quiet counters
Laravel framework 14 Aug 2026 4 min read

Laravel 13.20 Release: First-Party Image Processing and Quiet Eloquent Counters

Faisal Ahmed

Faisal Ahmed

Senior Full-Stack Developer

Laravel 13.20 is a feature release with one genuinely headline change — image processing moving into the framework itself — plus a batch of quality-of-life additions across queues, Eloquent, sessions and the HTTP client. If you are catching up on the 13.x line, it builds directly on what shipped in Laravel 13.5.

First-party image processing

The standout addition is first-party support for image processing. Resizing and manipulating uploads has historically meant reaching for Intervention Image or a similar package on every project. Bringing this into the framework means one less third-party dependency in the typical application that handles user uploads and thumbnails.

A follow-up fix in the same release stops stale transformations being reapplied when you branch an image — worth knowing if you build several derivatives from one source file, such as a feature image plus its thumbnail and social card.

Eloquent gets quiet counter updates

Eloquent picks up incrementEachQuietly and decrementEachQuietly. These do what the existing incrementEach and decrementEach do, but without firing model events.

That matters more than it sounds. Counter columns — view counts, stock levels, like totals — are exactly the kind of write you do not want triggering observers, cache invalidation or search reindexing on every hit. Previously you had to wrap the call in withoutEvents() yourself, which is easy to forget and easy to apply too broadly.

A companion fix makes sure the dynamic call forms of both methods behave correctly.

Skipping middleware with an attribute

Controllers can now declare middleware exclusions with a WithoutMiddleware attribute. This continues the framework's steady move toward PHP attributes for controller configuration — a direction that began in earnest around the Laravel 13 release — and keeps the exclusion next to the method it applies to rather than buried in a route file or constructor.

Queue and testing improvements

Several queue-related changes landed together:

  • Push hooks when faking the queuebeforePushing and afterPushing let you assert on what happens either side of a job being queued in tests.
  • Enums as overlap keys — you can now use an enum as a queue overlap key, so the key stays type-safe instead of being a loose string.
  • Memory usage on worker shutdown — the worker stopping event now carries memory usage, useful for tracking down workers that die to memory limits.
  • SQS size fallbacks — an operator precedence bug in the SQS queue size fallback has been fixed.

Sessions, storage and security

Redis-backed sessions can now be given a prefix. If you run several applications against one Redis instance, this is the change that stops their session keys colliding — a subtle bug that usually shows up as users being logged out of one app when they sign in to another.

On the storage side, assertEmpty joins the Storage facade's assertions, and providesTemporaryUploadUrls now correctly returns true for the S3 driver, which matters if you do direct-to-S3 uploads.

Security-adjacent housekeeping: #[SensitiveParameter] has been added to parameters that carry secrets. PHP redacts these from stack traces, so tokens and passwords are far less likely to end up in a log file or error reporting service. If you want more background on the attribute itself, it is part of the wider modern PHP toolkit covered in PHP 8.5 new features, changes and deprecations.

Fixes worth knowing about

A handful of the bug fixes in this release are the kind that silently affect existing code:

  • Str::containsAll() no longer returns true when given an empty needles array. If you pass a user-supplied array here, check your assumptions.
  • Number::forHumans() and abbreviate() no longer return "-0", and they handle very small decimals correctly.
  • make:migration generates collision-free, ordered timestamps — no more two migrations sharing a timestamp when you generate several in a row.
  • BelongsToMany::touch() works when the related key is not id.
  • Trusted proxy handling is fixed when multiple proxies are used — worth checking if you sit behind a CDN plus a load balancer.
  • JSON API resource relationships resolved through a closure now work as expected.

Should you upgrade?

Yes — this is a minor release within the 13.x line, so it follows semantic versioning and composer update should be uneventful for most applications. The two things to look at before deploying are the Str::containsAll() behaviour change and the number formatting fixes, since both alter output that existing code may depend on.

If you are still on an older major and weighing the jump, the differences are laid out in what shipped in Laravel 12 and in the Laravel 13 feature overview. For squeezing more out of whichever version you land on, Laravel Boost and Blaze for Blade component performance are both worth a look.

Disclaimer: Comments are moderated and may not appear immediately. Please avoid posting spam or offensive content.

// Keep Reading

Related Posts

No related posts found.

Stay Updated

Get the latest articles, tutorials, and tips delivered straight to your inbox.