Home / Symfony / New in Symfony 8.1: HTTP-Less Symfony Applications

New in Symfony 8.1: HTTP-Less Symfony Applications

This is the first article in a series showcasing the most important new features
introduced by Symfony 8.1, which will be released at the end of May 2026.


Symfony applications are typically built around handling HTTP requests. They do
so using the HttpKernel component, which provides a structured process for
converting a Request into a Response.

However, not all applications serve HTTP. Console commands, message consumers,
and background workers do not need the HTTP layer, but still rely on other parts
of Symfony such as the dependency injection container.

Until now, those applications still had to pull in the HttpKernel component,
even though they never used it. In Symfony 8.1, after considering this
problem for a long time, we’re finally making it possible to build
HTTP-less Symfony applications
.

Building HTTP-less Applications


Nicolas Grekas
Contributed by
Nicolas Grekas
in
#63710

Symfony 8.1 extracts the kernel and bundle infrastructure into the
DependencyInjection component, where it belongs, making HTTP-less Symfony
applications a reality.

The new SymfonyComponentDependencyInjectionKernel namespace provides
everything needed to build a kernel that boots the container, loads bundles,
and reads configuration without any HTTP-related code. To create a headless
kernel, extend AbstractKernel and use KernelTrait:

// src/Kernel.php
namespace App;

use SymfonyComponentDependencyInjectionKernelAbstractKernel;
use SymfonyComponentDependencyInjectionKernelKernelTrait;

class Kernel extends AbstractKernel
{
    use KernelTrait;
}

KernelTrait provides the same container lifecycle as MicroKernelTrait
(building, compiling, and caching the service container) but without any HTTP
logic. It follows the same conventions: config/bundles.php for bundle
registration, config/packages/ for configuration, and config/services.yaml
(or .php) for service definitions.

Decoupling the Kernel Interface from HTTP

Until Symfony 8.1, HttpKernelKernelInterface extended HttpKernelInterface.
Any service that needed to inspect bundles, the environment, or the cache
directory had to type-hint a kernel that also pulled in the HttpFoundation
component. Symfony 8.1 introduces a new KernelInterface in the
DependencyInjection component that exposes only the container-related API:

use SymfonyComponentDependencyInjectionKernelKernelInterface;

class BundleInspector
{
    public function __construct(private KernelInterface $kernel)
    {
    }
}

This change is fully backward compatible: HttpKernelKernel now extends the
new AbstractKernel, so existing applications keep working without any changes.

Opting Out of the Log Directory

HTTP-less applications often don’t need the conventional var/log/ directory.
In Symfony 8.1, getLogDir() is nullable on KernelTrait, so kernels can
opt out by setting the APP_LOG_DIR environment variable to false:

# .env
APP_LOG_DIR=false

Deprecated HttpKernel Classes

Three classes have moved from HttpKernel to the DependencyInjection component.
The original classes still work as backward-compatible aliases but are
deprecated:

  • SymfonyComponentHttpKernelBundleBundleInterface
    SymfonyComponentDependencyInjectionKernelBundleInterface
  • SymfonyComponentHttpKernelDependencyInjectionMergeExtensionConfigurationPass
    SymfonyComponentDependencyInjectionCompilerMergeExtensionConfigurationPass
  • SymfonyComponentHttpKernelConfigFileLocator
    SymfonyComponentDependencyInjectionKernelFileLocator

Building Simpler HTTP-Less Applications


Nicolas Grekas
Contributed by
Nicolas Grekas
in
#63880

Another friction point of HTTP-less console applications is pulling in the
full FrameworkBundle. In Symfony 8.1, its core has been split into two
standalone bundles:

  • SymfonyComponentDependencyInjectionKernelServicesBundle provides
    foundational DI services (event dispatcher, filesystem, clock, environment
    variable processors).
  • SymfonyComponentConsoleConsoleBundle provides console services
    (command registration, argument resolver, error listener).

A minimal console app only needs to register ConsoleBundle:

// config/bundles.php
return [
    SymfonyComponentConsoleConsoleBundle::class => ['all' => true],
];

In this example, ServicesBundle is loaded automatically as a dependency.
This is now possible thanks to #[RequiredBundle], a new attribute to define
dependency between bundles. You can use it in your own bundles too:

use SymfonyComponentDependencyInjectionKernelRequiredBundle;
use SymfonyComponentHttpKernelBundleAbstractBundle;

#[RequiredBundle(AcmeCoreBundle::class)]
#[RequiredBundle(AcmeUtilBundle::class, ignoreOnInvalid: true)]
class AcmeBlogBundle extends AbstractBundle
{
}

The attribute is repeatable, resolves recursively (if A requires B and B
requires C, all three are loaded in the right order) and accepts
ignoreOnInvalid: true to silently skip optional dependencies that aren’t
installed.


Sponsor the Symfony project.
Tagged:

Leave a Reply

Your email address will not be published. Required fields are marked *