Software & AI · From strategy to production

Technology · 9 December 2025 · 9 min read

Symfony 7.4 LTS or 8.x: how to choose the right version for your project in 2026?

As of September 2026, a Symfony application has two maintained paths: Symfony 7.4 LTS, with bug fixes until November 2028 (security until November 2029), or the 8.x branch, currently Symfony 8.1 (released at the end of May 2026, maintained until January 2027), followed by 8.2 in November 2026. Symfony 8.0 has been unmaintained since the end of July 2026. Our recommendation: 8.1 if your team can upgrade every six months, 7.4 LTS if your release cycles are heavy, and in that case a target of moving to 8.4 LTS, planned for November 2027.

This article, first published when 7.4 and 8.0 came out and updated in September 2026, helps you:

  • understand the difference between 7.4 LTS and the 8.x branch;
  • read the actual maintenance schedule;
  • spot the technical changes that matter;
  • build a concrete migration plan.

1. Symfony 7.4 and 8.0: same features, two strategies

Symfony releases its major versions in pairs: Symfony 8.0 = Symfony 7.4 without the deprecated features.

  • 7.4 contains the new features and all the compatibility layers: code that uses old APIs still works, with deprecation warnings.
  • 8.0 removes everything that is deprecated: the framework is lighter, but code that still uses the old APIs no longer works.

Since then, the two paths have diverged: 8.1 brought new features and 8.2 will follow in November 2026, while 7.4 only receives fixes.

1.1. The maintenance schedule as of September 2026

Version Type Released Minimum PHP Bug fixes until Security fixes until
Symfony 6.4 LTS Nov. 2023 8.1 Nov. 2026 Nov. 2027
Symfony 7.4 LTS Nov. 2025 8.2 Nov. 2028 Nov. 2029
Symfony 8.0 Standard Nov. 2025 8.4 July 2026 (end of life) July 2026 (end of life)
Symfony 8.1 Standard May 2026 8.4 Jan. 2027 Jan. 2027
Symfony 8.2 Standard Nov. 2026 (planned) 8.4 July 2027 July 2027
Symfony 8.4 LTS Nov. 2027 (planned) to be announced Nov. 2030 Nov. 2031

Source: symfony.com/releases, checked on September 30, 2026.

A standard version is maintained for eight months, so you need a minor upgrade every six months to stay covered. These upgrades (8.1 to 8.2, for example) follow Symfony’s backward compatibility promise: they are usually short if deprecations are handled as you go.

1.2. Our recommendation for your situation

  • New project: start on 8.1, then follow 8.2, 8.3 and 8.4 LTS. You get the new features and spread the migration effort.
  • Critical application (banking, healthcare, industry), heavy release processes, or bundles not yet 8.x-compatible: 7.4 LTS, with a target of moving to 8.4 LTS before 7.4’s bug fixes end in November 2028.
  • Application on 8.0: upgrade to 8.1 now; 8.0 no longer gets security fixes.
  • Application on 6.4: bug fixes stop in November 2026 and security fixes in November 2027. Plan the move to 7.4 now.
  • Application on 5.4 or older: the migration is a project in its own right, starting with a technical audit.

Symfony’s official recommendation points the same way: use the latest stable version whenever possible rather than staying frozen on an LTS.

2. Prerequisite: PHP 8.4 for the whole 8.x branch

Every 8.x version requires at least PHP 8.4. Symfony 7.4 accepts PHP 8.2, but the PHP release schedule is a reason to upgrade anyway:

PHP version Active support until Security fixes until
PHP 8.2 ended Dec. 31, 2026
PHP 8.3 ended Dec. 31, 2027
PHP 8.4 Dec. 31, 2026 Dec. 31, 2028
PHP 8.5 Dec. 31, 2027 Dec. 31, 2029

Source: php.net/supported-versions.

So before even talking about Symfony, the first question is: is our infrastructure ready for PHP 8.4 or 8.5? Servers, Docker images, CI pipeline, PHP extensions, Composer dependencies. We usually start with that inventory, then migrate the environment, before touching the Symfony application core.

3. FormFlow: native multi-step forms

This is one of the most visible changes in 7.4: multi-step forms (sign-up, onboarding, product configuration) are now native. Until now, you had to handle the session, progress tracking, Previous/Next buttons and partial validation by hand, or rely on a third-party bundle.

With FormFlow, you extend AbstractFlowType, declare the steps with addStep() and add a “navigator” for the buttons:

namespace App\Form;

use App\Model\UserSignUp;
use Symfony\Component\Form\Flow\AbstractFlowType;
use Symfony\Component\Form\Flow\FormFlowBuilderInterface;
use Symfony\Component\Form\Flow\Type\NavigatorFlowType;
use Symfony\Component\OptionsResolver\OptionsResolver;

final class UserSignUpType extends AbstractFlowType
{
    public function buildFormFlow(FormFlowBuilderInterface $builder, array $options): void
    {
        $builder->addStep('personal', UserSignUpPersonalType::class);
        $builder->addStep('professional', UserSignUpProfessionalType::class);
        $builder->addStep('account', UserSignUpAccountType::class);

        $builder->add('navigator', NavigatorFlowType::class);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => UserSignUp::class,
            'step_property_path' => 'currentStep',
        ]);
    }
}

In the controller, the flow is handled like a form, with two differences: isFinished() tells you whether the user has completed the flow, and getStepForm() renders the current step.

#[Route('/signup', name: 'app_signup')]
public function signUp(Request $request): Response
{
    $flow = $this->createForm(UserSignUpType::class, new UserSignUp())
        ->handleRequest($request);

    if ($flow->isSubmitted() && $flow->isValid() && $flow->isFinished()) {
        // persist $flow->getData()

        return $this->redirectToRoute('app_signup_success');
    }

    return $this->render('signup/flow.html.twig', [
        'form' => $flow->getStepForm(),
    ]);
}

The current step name is used as the validation group, so each step only validates its own fields. The result: less glue code, and complex forms that are easier to maintain.

4. Configuration: the end of XML, a new PHP format

  • The XML format is deprecated in 7.4 and removed in 8.0.
  • Fluent PHP configuration (the ConfigBuilder classes) is deprecated in 7.4, in favor of an array-based PHP format.

The new format reads like YAML but stays PHP. Symfony generates a config/reference.php file that describes the shape of every configuration (“array shapes”), so your IDE and static analysis tools (PHPStan, Psalm) can offer autocompletion and catch type errors.

An example security configuration with form login:

// config/packages/security.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;

return App::config([
    'security' => [
        'providers' => [
            'app_user_provider' => [
                'entity' => ['class' => \App\Entity\User::class, 'property' => 'email'],
            ],
        ],
        'firewalls' => [
            'main' => [
                'lazy' => true,
                'provider' => 'app_user_provider',
                'form_login' => [
                    'login_path' => 'app_login',
                    'check_path' => 'app_login',
                ],
                'logout' => ['path' => 'app_logout'],
            ],
        ],
        'access_control' => [
            ['path' => '^/admin', 'roles' => 'ROLE_ADMIN'],
        ],
    ],
]);

Watch out for older examples: the anonymous option has not existed since Symfony 6.0. A lazy firewall lets unauthenticated visitors through, and access_control decides who gets access.

YAML remains fully supported and is still the format Symfony recommends today. If you have XML, migrate it to YAML or to the new PHP format before moving to 8.x.

5. JSON, mapping and dates: Symfony gets stronger on APIs

Three components introduced as experimental in 7.3 are stable as of 7.4:

  1. JsonPath: query complex JSON structures with a dedicated syntax, useful for processing third-party API responses.
  2. JsonStreamer: encode and decode JSON quickly and with little memory, for large volumes (exports, ETL, microservices).
  3. ObjectMapper: map objects to other objects (entities, DTOs, API payloads) without writing that code by hand.

For dates, the input: 'date_point' option on date form fields and the DayPointType and TimePointType Doctrine types let you work with DatePoint and cleanly separate calendar dates (a due date, a birthday) from precise instants. For contracts, subscriptions and bookings, that means fewer time zone surprises.

6. Code quality: a stricter framework

6.1. The end of Request::get()

Request::get() is deprecated in 7.4 and removed in 8.0. It looked up a value in route parameters, the query string and the POST body all at once: ambiguous code, risk of collisions, harder validation. You now have to be explicit:

$request->attributes->get('id');   // route parameters
$request->query->get('page');      // ?page=…
$request->request->get('email');   // POST data

Or better, use mapping attributes in controllers: #[MapQueryParameter], #[MapQueryString], #[MapRequestPayload].

6.2. Invokable console commands

In 7.4, “invokable” commands (a class with an __invoke() method) gain interaction handling (#[Interact], #[Ask]), input mapping to a DTO (#[MapInput]) and enum support:

namespace App\Command;

use Symfony\Component\Console\Attribute\Argument;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Attribute\Option;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(name: 'app:invoices:send', description: 'Sends the invoices for the month')]
final class SendInvoicesCommand
{
    public function __invoke(
        SymfonyStyle $io,
        #[Argument] string $month,
        #[Option] bool $dryRun = false,
    ): int {
        // ...
        $io->success(sprintf('Invoices for %s processed.', $month));

        return Command::SUCCESS;
    }
}

6.3. UUID v7 by default and video validation

UuidFactory now generates UUID v7 by default: they embed a timestamp and index better in databases. A new Video constraint also lets you validate video files uploaded by users.

7. Migration plan: where to start?

If you are on Symfony 5.4, 6.4 or 7.0 to 7.3, here is a realistic plan:

  1. Upgrade the infrastructure: PHP 8.4 (or 8.5), extensions, Docker images, CI pipeline.

  2. Upgrade to Symfony 7.4 first: it is the “buffer” version, with all the features of 8.0 plus the compatibility layers.

  3. Hunt down deprecations by running the tests:

    php bin/phpunit --display-deprecations

    Fix what comes from your code (Rector automates a good share of the rewrites), and check that your third-party bundles have an 8.x-compatible release.

  4. Clean up the configuration: migrate XML to YAML or PHP, remove obsolete options.

  5. Go straight to the latest maintained 8.x, currently 8.1: there is no need to stop at 8.0. Plan a QA phase and performance tests.

  6. Set a rhythm: a minor upgrade every six months (8.2 in November 2026, 8.3, then 8.4 LTS in November 2027), and deprecations handled as part of normal technical debt management.

8. How we support you

We design, build and maintain business applications, including on Symfony. For a version upgrade, we step in at every stage:

  • Symfony and PHP audit: versions, dependencies, configuration, performance, security, mapping of deprecations and risks. That is the purpose of our technical audit.
  • Migration plan: choosing between 7.4 LTS and 8.x, with steps and a schedule that fit your product constraints.
  • Implementation: refactoring legacy code, moving complex forms to FormFlow, modernizing configuration, optimizing APIs. If the application also needs deeper changes, see modernize an application.
  • Upgrade rhythm: our teams build version upgrades into routine maintenance, so you no longer face big-bang migrations.

Every project has an Etixio tech lead who owns the technical choices, runs code reviews and remains your point of contact. Our teams work in your environment: your repositories, your ticketing tool, your security rules. Your code, your access, your tools: everything stays yours.

Once you are on 7.4 or 8.x, you can also add AI features to your application with Symfony AI, which supports both branches.

In summary

  • Symfony 8.0 is no longer maintained: today’s choices are 7.4 LTS or 8.1, then 8.2 in November 2026.
  • The 8.x branch requires PHP 8.4; even on 7.4, aim for PHP 8.4 or 8.5.
  • FormFlow, the new PHP configuration format, JsonStreamer, ObjectMapper and JsonPath are available on both branches.
  • The best migration is a regular one: handling deprecations as you go costs far less than a big migration every two years.

Want to prepare your Symfony 8 migration, secure your technical choices or have an existing Symfony application audited? Let’s talk: we will build a plan that fits your context with you.

FAQ

Is Symfony 8.0 still maintained?

No. Symfony 8.0 has received no fixes at all, neither bug nor security, since the end of July 2026. If your application runs on 8.0, move to 8.1: it is a minor upgrade, compatible with code that triggers no deprecations.

How long is Symfony 7.4 LTS maintained?

Symfony 7.4 receives bug fixes until November 2028 and security fixes until November 2029. It no longer gets new features.

Which PHP version does Symfony 8 require?

Every 8.x version requires at least PHP 8.4. Symfony 7.4 runs on PHP 8.2 and later, but PHP 8.2 gets no security fixes after December 31, 2026: aim for PHP 8.4 or 8.5 either way.

Do I need to go through Symfony 8.0 to get from 7.4 to 8.1?

No. Once deprecations are fixed on 7.4, you can upgrade directly to the latest maintained 8.x version, currently 8.1.

Keep reading

Read also

Let’s move forward together

What’s your next project?

Let’s talk about your challenges and define the right support.

Book a 30-min call with a tech lead

What are you looking for?