Laravel · Laravel

Laravel 11 New Features — A Complete Guide

What actually changed in Laravel 11: the slimmer application skeleton, per-second rate limiting, health check routing, new artisan commands, and what upgrading from Laravel 10 involves.

John Kihiu12 min read

Laravel 11's headline change isn't a new feature so much as a restructuring: a much slimmer default application skeleton, with most of the boilerplate that used to live in app/Http/Kernel.php, multiple service providers, and scattered config files consolidated into bootstrap/app.php. If you've maintained a Laravel app across several major versions, this is the release where the framework finally acted on years of "why do new projects start with so many files nobody touches."

The slimmer application skeleton

A fresh Laravel 11 install no longer ships a separate Kernel.php for HTTP or console, no default app/Console/Kernel.php, and far fewer service provider files — middleware registration, exception handling, and route model binding customisation all move into a fluent, chainable configuration inside bootstrap/app.php. Existing Laravel 10 apps aren't forced onto this structure when upgrading; the old structure still works, it's specifically new projects that get the leaner skeleton. If you're maintaining an older app, the practical upgrade work is dependency version bumps, not a structural rewrite.

PHP · bootstrap/app.php
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->throttleApi();
    })
    ->withExceptions(function (Exceptions $exceptions) {
        $exceptions->report(function (InvalidOrderException $e) {
            // custom reporting
        });
    })->create();

Built-in health check routing

The health: '/up' line above is new in Laravel 11 — a zero-config health check endpoint that returns a 200 as long as the application booted, useful for load balancer and container orchestrator health probes without writing a custom route and controller for it. It's intentionally minimal (it doesn't check database or cache connectivity by default), so for a real production readiness probe you still want your own endpoint that checks the dependencies that actually matter to you.

Per-second rate limiting

Laravel's rate limiter previously only supported per-minute granularity. Laravel 11 adds per-second rate limits, which matters for APIs where a per-minute cap is too coarse to stop a short burst from overwhelming a downstream service — think a webhook receiver or a third-party API proxy where you need to smooth traffic within a single second, not just across a minute.

PHP · RouteServiceProvider / bootstrap/app.php
RateLimiter::for('webhooks', function (Request $request) {
    return Limit::perSecond(5)->by($request->ip());
});
New artisan commands worth knowing

php artisan make:class and php artisan make:enum were added for scaffolding plain classes and native PHP enums consistently with the rest of Laravel's generators, and php artisan about --only=environment style filtering makes the diagnostics command more useful in CI scripts than parsing the full table output.

Model casts as a method instead of a property

Eloquent models can now define an optional casts() method instead of (or alongside) the $casts property, which lets you build cast definitions dynamically — passing arguments to a custom cast class, for example — something the static array property couldn't express. The old $casts property still works; this is additive, not a deprecation.

PHP · app/Models/Order.php
protected function casts(): array
{
    return [
        'options' => AsCollection::class,
        'status' => OrderStatus::class,
        'discount' => AsEncryptedCollection::class,
    ];
}

What upgrading from Laravel 10 actually involves

Laravel 11 requires PHP 8.2 minimum, and if you're on an LTS-adjacent app you're mostly checking that your dependencies (Sanctum, Horizon, third-party packages) have released Laravel 11-compatible versions before running composer update. The skeleton changes don't force a rewrite of an existing app's structure — you keep your Kernel.php files if you have them — so the real upgrade cost is almost entirely dependency compatibility, not adapting to the new conventions.

Wrapping up

Laravel 11's real contribution is subtraction: a smaller default skeleton, consolidated configuration in bootstrap/app.php, plus genuinely useful additions like per-second rate limiting, zero-config health routing, and method-based casts. None of it forces existing applications to restructure — the new skeleton only applies to fresh installs — so upgrading is mostly a dependency-compatibility exercise rather than a rewrite.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.