->refundedTwice(). That is the line from Laravel 8 I care about, and it is nowhere on the release page. Jetstream gets the screenshots. Class-based factories and the queue changes get my attention, because both are about production.

Factories used to be closures registered through a global function. Now they are classes with states:

Order::factory()
    ->paid()
    ->has(OrderItem::factory()->count(3))
    ->create();

Test data quality decides test quality. Most integration suites on our project test the happy path fifty times, because the default factory returns a fresh, valid, boring record. The bugs live somewhere else. An order refunded twice. A user registered before the migration added the column. A subscription that expired in the middle of renewal. A factory state gives such a monster a name, and once the name exists, people write tests with it. Named ugly data is the cheapest test improvement I know.

Queues: retries, backoff, retryUntil, and now job batching. The API is fine. The mental shift matters more. A queued job is a small distributed system. It can run twice, run late, or run after the row it references has changed. Laravel 8 gives better tools for the retry choreography. Deciding what “safe to run twice” means for your order is still your job.

One caution. Every version adds conveniences, and conveniences are pleasant right until someone mistakes them for architecture. Facades, magic scopes, implicit bindings: tools. The structure has to survive the day you swap them.

The upgrade is calm. Factories need a namespace move, there is a shim package for the transition. Do it before the suite grows another hundred closure factories. Ours has more than I want to count, and I have been saying “next sprint” since 7.0.