Key takeaways
- You can go from v3 to v5 in a single branch, but not in a single step. Run the v4 upgrade script first, then the v5 script.
- Almost all the real work is the v3 → v4 jump: unified actions, the new
SchemaAPI, Tailwind CSS v4 themes and a handful of changed defaults. - Most changed defaults can be reverted globally with
configureUsing()in a service provider, which keeps the upgrade diff small. - Filament v3 stopped getting bug fixes on 1 August 2026. Security fixes continue until 1 January 2028.
Plenty of production panels are still on Filament v3. Maybe v4 arrived mid-project, or the “v4 is a big one” warnings put you off. Now there’s a v5, and the obvious question is whether you can skip straight to it.
Yes, and in 2026 it’s the sensible thing to do. Filament v5 is Filament v4 plus Livewire 4 support, so upgrading to v4 and stopping there saves you almost nothing. This guide shows how to make the jump safely in one branch, with two automated passes and a short list of manual fixes.
Why you can’t do it in one command
Each upgrade script only knows about one version jump:
filament/upgrade:^4.0(run withvendor/bin/filament-v4) contains the Rector rules that rewrite v3 code into v4 code: namespaces, method renames, the new schema API.filament/upgrade:^5.0(run withvendor/bin/filament-v5) only checks for v4 → v5 issues, which is mostly the Livewire 4 move.
If you require filament/filament:^5.0 directly on a v3 codebase, Composer will install it, but none of your v3 code gets rewritten and the panel won’t boot. So the method is two passes, one branch, one deploy. You never ship v4 to production.
Check your platform first
| Requirement | Filament v3 | Filament v5 |
|---|---|---|
| PHP | 8.1+ | 8.2+ |
| Laravel | 10+ | 11.28+ (12 and 13 supported) |
| Livewire | 3 | 4 (^4.1 on current releases) |
| Tailwind CSS (custom theme) | v3 | v4 |
| doctrine/dbal | Required | No longer required by Filament |
If you’re on Laravel 10, upgrade Laravel first as a separate, deployed step. Mixing a framework upgrade with a Filament rewrite makes failures hard to diagnose. If you want to end up on Laravel 13, read our Laravel 13 compatibility checklist, which covers the PHP 8.3 minimum.
If your app uses doctrine/dbal for its own reasons (old column-change migrations, for example), add it to composer.json directly. Filament v4 stopped pulling it in.
Pass 1: Filament v3 → v4
Run the v4 upgrade script
git checkout -b upgrade/filament-v5
composer require filament/upgrade:"^4.0" -W --dev
vendor/bin/filament-v4
# Run the commands the script prints, then:
composer require filament/filament:"^4.0" -W --no-update
composer updateIf installing the script fails, the v4 upgrade guide points out that it uses Rector 2. That means you need PHPStan 2+ or Larastan 3+. Bump those first.
Commit straight after the script runs. Its diff is large and mechanical, and you want it in a separate commit from your manual fixes.
Decide on the new directory structure
Filament v4 introduced a new default layout for resources, with each resource in its own folder and separate Schemas and Tables classes. You can keep the old structure or migrate:
php artisan filament:upgrade-directory-structure-to-v4 --dry-run
php artisan filament:upgrade-directory-structure-to-v4The command can’t fix every reference between classes in the same namespace, so run PHPStan afterwards to catch broken imports. If you migrate, you’ll match the generators and the docs from now on, which makes life easier for both people and AI coding agents.
Publish the config and keep v3 file behaviour
php artisan vendor:publish --tag=filament-configTwo settings matter here. The default filesystem disk now follows FILESYSTEM_DISK, not FILAMENT_FILESYSTEM_DISK, and new code generation has different defaults. To keep v3 behaviour:
// config/filament.php
use Filament\Support\Commands\FileGenerators\FileGenerationFlag;
return [
'default_filesystem_disk' => env('FILAMENT_FILESYSTEM_DISK', 'public'),
'file_generation' => [
'flags' => [
FileGenerationFlag::EMBEDDED_PANEL_RESOURCE_SCHEMAS,
FileGenerationFlag::EMBEDDED_PANEL_RESOURCE_TABLES,
// Only if you did NOT run the directory upgrade command:
FileGenerationFlag::PANEL_RESOURCE_CLASSES_OUTSIDE_DIRECTORIES,
FileGenerationFlag::PANEL_CLUSTER_CLASSES_OUTSIDE_DIRECTORIES,
],
],
];The manual breaking changes, in order of pain
The script handles namespaces and renames. It doesn’t change behaviour you depended on. These are the changes that surprise v3 teams:
- File visibility is private on non-local disks.
FileUpload,ImageColumnandImageEntrynow default toprivatevisibility on disks like S3, so images load through temporary signed URLs. Public buckets suddenly show broken images, and generating signed URLs can slow tables down. - Table filters are deferred. Users now click “Apply” before filters run.
Grid,SectionandFieldsetno longer span the full width by default. Two-column resource forms suddenly put sections side by side.unique()ignores the current record by default. This is usually what you wanted anyway, but check any code that relied on the old behaviour.- The
'all'pagination option is gone by default. Good for performance, but some users will complain. - Custom themes need Tailwind CSS v4. More on this below.
- Tailwind classes in your own views stop working without a custom theme. Filament’s views now use
@applyin CSS, so utility classes you “borrowed” from Filament’s compiled stylesheet are no longer included.
You can reverse items 1, 2, 3, 4 and 5 globally, which keeps the upgrade small. Put this in AppServiceProvider::boot() and remove each line later, when you’re ready to adopt the new default:
use Filament\Forms\Components\Field;
use Filament\Forms\Components\FileUpload;
use Filament\Infolists\Components\ImageEntry;
use Filament\Schemas\Components\Fieldset;
use Filament\Schemas\Components\Grid;
use Filament\Schemas\Components\Section;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Table;
public function boot(): void
{
// 1. Keep public file visibility on S3-style disks
FileUpload::configureUsing(fn (FileUpload $c) => $c->visibility('public'));
ImageColumn::configureUsing(fn (ImageColumn $c) => $c->visibility('public'));
ImageEntry::configureUsing(fn (ImageEntry $c) => $c->visibility('public'));
// 2 + 5. Instant filters and the "all" page option
Table::configureUsing(fn (Table $table) => $table
->deferFilters(false)
->paginationPageOptions([5, 10, 25, 50, 'all']));
// 3. Full-width layout components
Fieldset::configureUsing(fn (Fieldset $c) => $c->columnSpanFull());
Grid::configureUsing(fn (Grid $c) => $c->columnSpanFull());
Section::configureUsing(fn (Section $c) => $c->columnSpanFull());
// 4. v3-style unique() validation
Field::configureUsing(fn (Field $f) => $f->uniqueValidationIgnoresRecordByDefault(false));
}Other changes to review, depending on what you use:
columnSpan(2)now targetslgand up, the same ascolumns(). Code that used['lg' => 2]can be simplified.- Enum fields always return enum instances.
Select,RadioandCheckboxListbound to an enum no longer sometimes return the raw value. - URL query parameters were renamed:
tableFilters→filters,tableSearch→search,activeRelationManager→relation, and so on. Bookmarked filtered URLs and customgetUrl()calls break. - Tenancy now scopes every query in the panel automatically and associates new records with the tenant. Remove manual scoping you added in v3, or you may end up filtering twice.
- Overriding
canCreate()/canEdit()on resources. These aren’t always called any more. Move the logic to policies or override theget*AuthorizationResponse()methods. - Tables sort by primary key by default. Disable it with
->defaultKeySort(false)if your table has no key. - Import and export jobs now retry three times with a 60-second backoff, instead of hammering for 24 hours.
- The Spatie Translatable plugin is deprecated. Switch to the Lara Zeus fork. The upgrade script suggests the Composer commands for this.
The API shape you’ll see after the script
After the script runs, your resources will look different. This is roughly what a v3 table and form look like in v4/v5, so you can recognise the result and write new code the same way:
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction; // was Filament\Tables\Actions\EditAction
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Section; // was Filament\Forms\Components\Section
use Filament\Schemas\Schema; // was Filament\Forms\Form
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
public static function form(Schema $schema): Schema
{
return $schema->components([ // was $form->schema([...])
Section::make('Details')->schema([
TextInput::make('name')->required(),
]),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([TextColumn::make('name')->searchable()])
->recordActions([EditAction::make()]) // was ->actions()
->toolbarActions([ // was ->bulkActions()
BulkActionGroup::make([DeleteBulkAction::make()]),
]);
}Get and Set moved to Filament\Schemas\Components\Utilities. Infolists also use Schema now, and every action lives under Filament\Actions.
Migrate your theme to Tailwind CSS v4
If you have resources/css/filament/admin/theme.css, replace the old @config line with @source entries:
@import '../../../../vendor/filament/filament/resources/css/theme.css';
@source '../../../../app/Filament/**/*';
@source '../../../../resources/views/filament/**/*';
/* add paths from the old tailwind.config.js "content" array */Then run Tailwind’s official upgrade tool and move any tailwind.config.js customisations into CSS:
npx @tailwindcss/upgrade
npm run buildIf you never had a custom theme but used Tailwind classes in your own Filament views, create one now with php artisan make:filament-theme. Our Filament theming guide walks through it.
At this point, boot the app and run your tests on v4. Don’t move on until Pass 1 is green.
Pass 2: Filament v4 → v5
This is the short one:
composer remove filament/upgrade --dev
composer require filament/upgrade:"^5.0" -W --dev
vendor/bin/filament-v5
composer require filament/filament:"^5.0" -W --no-update
composer update
composer remove filament/upgrade --devThen work through the Livewire 4 changes that affect custom code: renamed config keys, wire:model.blur needing .live, closed <livewire:... /> tags, the removed wire:transition modifiers, and the new /livewire-{hash}/ endpoints. Our Filament v4 to v5 upgrade guide covers each one with search commands to find them.
Plugins: audit before you start, not halfway through
Plugin compatibility is the main reason v3 → v5 upgrades stall. Before Pass 1, list every Filament plugin and check it:
composer show | grep -i filament
composer why-not filament/filament 5.0For each plugin, you’ll find one of three things:
- It supports
^4.0|^5.0. Just bump its constraint. Most major plugins are here, including Shield 4.x, Breezy, Filament Excel, Curator and Apex Charts. - It has a v5-only major. Bump to that major and read its changelog. Shield 4.x, for example, is a full rewrite with new permission names.
- It’s abandoned. Replace it, or check whether v4/v5 core now does the job. Filament v4 added a TipTap rich editor, table-mode repeaters, built-in multi-factor authentication and slider and code editor fields. Several v3-era plugins became unnecessary.
Rollout checklist
- Staging gets a copy of production data, with S3 credentials if you use private files.
- Clear every cache:
php artisan optimize:clear, thenphp artisan filament:optimize. - Rebuild front-end assets in CI, not on the server.
- Update WAF/CDN rules for Livewire 4’s
/livewire-{hash}/paths. - Tell users about deferred filters and the new layout, or keep the v3 defaults with the snippet above.
- Keep the v3 release tagged. Rollback means redeploying that tag, since the database schema only changes if you published and ran new Filament migrations (the imports/exports tables, for example).
FAQ
Can I upgrade Filament v3 directly to v5?
Yes, in one branch, but run the v4 upgrade script before the v5 script. The v5 script doesn’t contain the Rector rules that convert v3 code.
How long does a v3 to v5 upgrade take?
A small panel with a few resources and no custom theme typically takes half a day. Large panels with custom themes, many plugins and custom Livewire components can take several days, mostly spent on plugins and visual regressions.
Will my v3 resource classes still work?
After the v4 script runs, yes. It rewrites namespaces and method names. Behavioural defaults (deferred filters, layout spans, file visibility) change, but you can restore them with configureUsing().
Is Filament v3 still supported?
Only for security. Bug fixes ended on 1 August 2026. Security fixes continue until 1 January 2028, per the version support policy.
Do I have to migrate to the new directory structure?
No. It’s optional, and you can keep v3-style file generation with the file_generation flags. New projects and the docs use the new layout, though.
Sources and further reading
- Filament v4 upgrade guide
- Filament v5 upgrade guide
- Livewire 4 upgrade guide
- Tailwind CSS v4 upgrade guide
Filament version support policy
Related on The Web Tier: Filament v5 vs v4 · Best Filament plugins
