TYPO3 v13 is a major step forward. It removes legacy APIs, tightens core architecture, and introduces stricter standards that directly affect custom code and extensions.
This guide focuses on what matters during an upgrade: breaking changes that must be fixed, important changes that may alter behaviour, and deprecations that need attention before TYPO3 v14. Use it as a practical reference to plan, execute, and stabilise your TYPO3 v13 migration with fewer surprises.
Who This Guide Is For and Who It Is Not
This guide is for teams planning a serious upgrade to TYPO3 v13. It focuses on real migration work and long-term maintenance, not feature marketing.
This guide is for
- TYPO3 agencies managing multiple client projects and LTS upgrades
- Freelance TYPO3 developers maintaining custom extensions and site packages
- In-house TYPO3 teams running long-living, business-critical websites
- Technical leads and CTOs planning upgrade scope, risk, and timelines
This guide is not for
- Beginners new to TYPO3
- Marketing or content-only roles
- Projects running close to TYPO3 core without custom code or extensions
What you will gain
- Clarity on which breaking changes require immediate action
- Guidance on what can be postponed without upgrade risk
- A practical view on preparing TYPO3 v13 projects for v14
Upgrade Reality in TYPO3 v13
TYPO3 upgrades are not just technical tasks. They are planning exercises shaped by long lifecycles, extension dependencies, and limited upgrade windows.
Long LTS Cycles Shape Every Decision
TYPO3 projects often run 3–6 years on one LTS version.
That means:
- Old decisions stay in production longer
- Technical debt compounds quietly
- Upgrade mistakes are expensive to undo
v13 upgrades should be treated as structural resets, not quick version bumps.
Extension-First Dependency Reality
Most TYPO3 installations depend more on extensions than core.
In practice:
- Core upgrades block on extension readiness
- Custom extensions are the highest-risk area
- TER extensions vary widely in maintenance quality
Always audit extensions before touching custom code.
What to Fix First (Blocking Issues)
Fix these before or during the upgrade:
- Breaking changes that cause PHP errors or fatal exceptions
- Removed hooks replaced by PSR-14 events
- QueryBuilder, Doctrine, and Symfony incompatibilities
- Deprecated APIs scheduled for removal in v14
These will break the site, not just log warnings.
What Can Wait (Post-Upgrade Cleanup)
These can be scheduled after stabilization:
- Deprecated but still functional APIs
- Internal refactoring for cleaner architecture
- Performance tuning unrelated to v13 changes
Delaying these is acceptable, but track them.
This mindset keeps TYPO3 v13 upgrades predictable, controlled, and aligned with long-term maintenance, not just version compliance.
Practical Upgrade Guidance for TYPO3 v13 Projects
This section focuses on what actually reduces upgrade time and risk in real TYPO3 projects. It reflects patterns seen across agency deliveries, long-running sites, and extension maintenance.
Recommended Upgrade Path
- Upgrade to the latest TYPO3 v12 LTS first.
- Resolve all deprecations and extension warnings in v12.
- Only then move to v13, using the core upgrade wizards.
- Avoid skipping major versions on active projects.
This two-step path catches most breaking changes early and keeps rollback simple.
Pre-Upgrade Checks (Do These First)
- Confirm all extensions are v13-compatible or maintained.
- Remove unused or abandoned TER extensions.
- Run TYPO3 deprecation logs and fix warnings in v12.
- Check custom code for:
- Hook usage (stdWrap, TSFE, IconFactory)
- QueryBuilder and Doctrine usage
Backend JavaScript module imports
Skipping these checks is the most common cause of failed upgrades.
Upgrade Sequence That Actually Works
- Update PHP and system requirements.
- Upgrade TYPO3 core via Composer.
- Run all Install Tool wizards.
- Clear caches and recheck backend access.
- Fix fatal errors before touching frontend output.
Do not debug frontend issues until the backend is stable.
Post-Upgrade Validation
- Test backend forms, RTE, and custom modules.
- Verify login, permissions, and workspaces.
- Check CLI commands and scheduler tasks.
- Review logs for remaining deprecations or notices.
Most hidden issues appear in backend workflows, not pages.
Common Mistakes TYPO3 Teams Make
- Treating deprecations as optional cleanup.
- Keeping legacy hooks instead of moving to PSR-14.
- Mixing runtime fixes with Composer updates.
- Letting strict typing issues surface in production.
These increase long-term maintenance costs, not just upgrade effort.
Extension Author Perspective (What Matters Now)
TYPO3 v13 enforces clearer architecture:
- PSR-14 events replace most legacy hooks.
- Strict typing is no longer optional in Extbase.
- Composer discipline matters for dependency stability.
Extensions that follow these rules upgrade cleanly. Others become technical debt quickly.
TYPO3 v13 vs TYPO3 v14 - Upgrade Readiness Overview
This table helps teams understand which changes are mandatory now and which are future blockers. It is ideal for AI snippets and featured answers.
| Area | TYPO3 v13 Status | TYPO3 v14 Impact | What Teams Should Do |
| Legacy Hooks | Removed | Not available | Migrate fully to PSR-14 events |
| QueryBuilder APIs | Changed | Stable | Update now; v14 will not support legacy calls |
| Extbase Typing | Enforced | Stricter | Fix type hints and method signatures |
| $GLOBALS['TSFE'] | Deprecated | Removed | Use Context API or request attributes |
| Fluid renderStatic() | Deprecated | Removed | Refactor ViewHelpers |
| Plugin via list_type | Deprecated | Removed | Use dedicated CType per plugin |
| CKEditor config fallbacks | Removed | Stable | Use explicit YAML arrays |
| Backend JS legacy modules | Deprecated | Removed | Switch to modern ES modules |
| PageTS via API | Deprecated | Removed | Move to configuration files |
| Datetime INT fields | Changed | Stable | Ensure BIGINT usage |
Key takeaway:
A TYPO3 v13 upgrade that ignores deprecations is only half done. Fixing them now dramatically lowers v14 effort.
TYPO3 v13 Upgrade Changes, Risk-Based Overview
TYPO3 v13 introduces significant internal changes. Not all of them require the same level of urgency. To support realistic upgrade planning, the changes below are grouped by actual project risk, not by changelog category.
This helps teams decide:
- What must be fixed before upgrading
- What needs testing after the upgrade
- What can be handled later as cleanup for v14
High-Risk Changes (Must Be Fixed Before or During Upgrade)
These changes will break functionality or cause fatal errors if not addressed.
QueryBuilder and Database API Changes
ExpressionBuilder Changes
The method signatures have changed:
ExpressionBuilder::literal()now strictly requires a stringExpressionBuilder::trim()now requires theTrimModeenum
Before v13
$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim($fieldName, 1),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);
After v13
use Doctrine\DBAL\Platforms\TrimMode;
$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim($fieldName, TrimMode::LEADING),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);
QueryBuilder API Changes
Removed methods include:
add()
getQueryPart(), getQueryParts()
resetQueryPart(), resetQueryParts()
execute()
setMaxResults(0)
Required changes
- Use
executeQuery()for SELECT - Use
executeStatement()for INSERT / UPDATE / DELETE - Use
nullinstead of0for unlimited results
Before v13
$queryBuilder->add('select', ['uid', 'title']);
$result = $queryBuilder->execute();
$queryBuilder->setMaxResults(0);
After v13
$queryBuilder->select('uid', 'title');
$result = $queryBuilder->executeQuery();
$queryBuilder->setMaxResults(null);
Authentication and Context Access
LoginType Converted to Native Enum
\TYPO3\CMS\Core\Authentication\LoginType is now a PHP enum.
Old constants are removed.
Before v13
if ($loginType === \TYPO3\CMS\Core\Authentication\LoginType::LOGIN) {
// ...
}
After v13
use TYPO3\CMS\Core\Authentication\LoginType;
if (LoginType::tryFrom($value ?? '') === LoginType::LOGIN) {
// login
}
$TSFE->fe_user Removed
Direct access to frontend user data via $TSFE is no longer available.
Before v13
$username = $GLOBALS['TSFE']->fe_user->user['username'];
After v13 (Context API)
use TYPO3\CMS\Core\Context\Context;
$username = $this->context
->getPropertyFromAspect('frontend.user', 'username', '');
After v13 (Request attribute)
$frontendUser = $this->request->getAttribute('frontend.user');
$username = $frontendUser->user['username'] ?? '';
Removed Hooks (PSR-14 Required)
The following hooks are fully removed and will cause failures if still referenced:
stdWraphookgetDatahookpostInithook- Icon overlay override hook
Action required
- Remove hook registrations
- Replace with corresponding PSR-14 events
Backend Layout Provider Change
PageTsBackendLayoutDataProvider Marked Final
\TYPO3\CMS\Backend\View\BackendLayout\PageTsBackendLayoutDataProvider can no longer be extended.
Before v13
class MyProvider extends PageTsBackendLayoutDataProvider {
}
After v13
class MyProvider implements BackendLayoutDataProviderInterface {
}
Medium-Risk Changes (Behaviour Changes After Upgrade)
These changes may not crash the system but alter behaviour, output, or editor experience.
CKEditor Configuration Change
removePlugins Fallback Removed
String-based configuration is no longer supported.
Before v13
editor:
config:
removePlugins: image
After v13
editor:
config:
removePlugins:
- image
Indexed Search Changes
Indexed Search Declared as Content Element
EXT:indexed_search is now a CType instead of a plugin.
Action
- Run upgrade wizard:
“Migrate Indexed Search plugins to content elements”
Pagination Changes
getAllPageNumbers() Removed
This method no longer exists.
Action
- Use
getFirstPageNumber() - Use
getLastPageNumber() - Or implement custom iteration logic
Utility Behaviour Changes
Continuous Array Keys in intExplode()
When removeEmptyEntries = true, keys are now continuous.
Before
[0 => 1, 2 => 3]
After
[0 => 1, 1 => 3]
Editor & Wizard Behaviour
New Content Element Wizard Derived from TCA
show := removeFromList() no longer works.
Required change
removeItems := addToList(html)
SEO & Link Validation
External Link Validation Disabled by Default
EXT:linkvalidator no longer checks external links unless enabled.
Action
mod.linkvalidator.linktypes = db,file,external
Default twitter_card Changed
Default value changed from summary to summary_large_image.
Low-Risk Changes (Cleanup and v14 Preparation)
These changes do not block TYPO3 v13 but should be addressed to reduce future upgrade effort.
Database & Schema
BIGINT for Datetime Fields
Datetime TCA fields now use BIGINT to avoid the year-2038 problem.
Before
crdate INT(11) DEFAULT '0'
After
crdate BIGINT(20) DEFAULT '0'
Dependency Updates
- Symfony upgraded to version 7
- Doctrine DBAL upgraded to version 4
These are mostly covered by QueryBuilder fixes above.
Removed Legacy Structures
- Unused
tt_contentfields removed cache_treelisttable removed
Only impacts projects still referencing them.
Indexed Search Customisation
Manipulating final search queries in EXT:indexed_search has changed. Only relevant if custom logic exists.
How to Apply This in Practice
- Fix High-Risk changes before upgrading
- Test Medium-Risk changes during QA
- Schedule Low-Risk changes as cleanup
This avoids unnecessary work and keeps TYPO3 upgrades predictable and controlled.
Deprecations (Prepare for TYPO3 v14)
The following APIs and patterns are still available in TYPO3 v13, but will be removed in TYPO3 v14. They do not block an immediate upgrade, but leaving them unresolved will increase future upgrade effort.
Recommendation:
Fix these during v13 upgrade work where possible, especially in extensions you actively maintain.
1. ExtensionManagementUtility::addPageTSConfig()
This method is deprecated and will be removed in v14.
What to do:
Move Page TS configuration into a dedicated Configuration/page.tsconfig file.
2. DuplicationBehavior Class
The legacy class is deprecated.
Before:
$behavior = \TYPO3\CMS\Core\Resource\DuplicationBehavior::RENAME;
After:
$behavior = \TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior::RENAME;
3. AbstractFile::FILETYPE_* Constants
All AbstractFile::FILETYPE_* constants are deprecated.
Before:
\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_UNKNOWN
\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_TEXT
\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_IMAGE
\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_AUDIO
\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_VIDEO
\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_APPLICATION
After:
\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_UNKNOWN -> \TYPO3\CMS\Core\Resource\FileType::UNKNOWN->value
\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_TEXT -> \TYPO3\CMS\Core\Resource\FileType::TEXT->value
\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_IMAGE -> \TYPO3\CMS\Core\Resource\FileType::IMAGE->value
\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_AUDIO -> \TYPO3\CMS\Core\Resource\FileType::AUDIO->value
\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_VIDEO -> \TYPO3\CMS\Core\Resource\FileType::VIDEO->value
\TYPO3\CMS\Core\Resource\AbstractFile::FILETYPE_APPLICATION -> \TYPO3\CMS\Core\Resource\FileType::APPLICATION->value
Apply the same change for TEXT, AUDIO, VIDEO, APPLICATION, and UNKNOWN.
4. DataProviderContext Getters and Setters
Since TYPO3 v13.4, DataProviderContext uses constructor property promotion and is moving to a readonly, final class in v14.
Before (setter-based):
$dataProviderContext = GeneralUtility::makeInstance(DataProviderContext::class);
$dataProviderContext
->setPageId($pageId)
->setData($parameters['row'])
->setTableName($parameters['table'])
->setFieldName($parameters['field'])
->setPageTsConfig($pageTsConfig);
After (constructor-based):
$dataProviderContext = new DataProviderContext(
pageId: $pageId,
tableName: $table,
fieldName: $field,
data: $row,
pageTsConfig: $pageTsConfig
);
Access properties directly instead of getters.
Before
$pageId = $dataProviderContext->getPageId()
After
$pageId = $dataProviderContext->pageId
5. TypoScriptFrontendController and $GLOBALS['TSFE']
TypoScriptFrontendController and $GLOBALS['TSFE'] are deprecated and removed in v14.
What to do:
Use request attributes or the Context API.
Before v13
$feUser = $GLOBALS['TSFE']->fe_user->user;
After v13
use TYPO3\CMS\Core\Context\Context;
$feUser = GeneralUtility::makeInstance(Context::class)
->getPropertyFromAspect('frontend.user', 'user');
6. Fluid Standalone Methods
Several standalone Fluid methods like TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper->registerUniversalTagAttributes() and AbstractTagBasedViewHelper->registerTagAttribute() are deprecated.
Impact:
Custom ViewHelpers may trigger warnings.
Action:
Review Fluid extensions and follow current Fluid API documentation.
7. Table-Dependent columnsOnly Definition
The columnsOnly parameter must now be defined per table.
Before:
$urlParameters = [
'edit' => [
'pages' => [
1 => 'edit',
],
],
'columnsOnly' => 'title,slug'
'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(),
];
GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute('record_edit', $urlParameters);
After:
$urlParameters = [
'edit' => [
'pages' => [
1 => 'edit',
],
],
'columnsOnly' => [
'pages' => [
'title',
'slug'
]
],
'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(),
];
GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute('record_edit', $urlParameters);
8. Namespaced Shorthand Validators in Extbase
Namespaced shorthand validator notation is deprecated.
Before:
/**
* @Extbase\Validate("TYPO3.CMS.Extbase:NotEmpty")
*/
protected $myProperty1;
/**
* @Extbase\Validate("Vendor.Extension:Custom")
*/
protected $myProperty2;
After:
/**
* @Extbase\Validate("NotEmpty")
*/
protected $myProperty1;
/**
* @Extbase\Validate("Vendor\Extension\Validation\Validator\CustomValidator")
*/
protected $myProperty2;
Or
#[Extbase\Validate(['validator' => \TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator::class])]
protected $myProperty1;
#[Extbase\Validate(['validator' => \Vendor\Extension\Validation\Validator\CustomValidator::class])]
protected $myProperty2;
Custom validators must use full class names.
9. Custom Fluid Views in Extbase
StandaloneView, TemplateView, and related classes are deprecated.
Replacement:
Use ViewFactoryInterface.
This affects custom Extbase rendering logic.
10. renderStatic() in Fluid ViewHelpers
renderStatic() and related traits are deprecated.
Before:
class MyViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext): string
{
return $renderChildrenClosure();
}
}
After:
class MyViewHelper extends AbstractViewHelper
{
public function render(): string
{
return $this->renderChildren();
}
}
Refactor ViewHelpers accordingly.
11. IconRegistry Instantiation in ext_localconf.php
Manual icon registration in ext_localconf.php is deprecated.
Before v13
EXT:example/ext_localconf.php
<?php
$iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class,);
$iconRegistry->registerIcon(
'example',
\TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
[
'source' => 'EXT:example/Resources/Public/Icons/example.svg'
],
);
Nach v13
EXT:example/Configuration/Icons.php
<?php
return [
'example' => [
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
'source' => 'EXT:example/Resources/Public/Icons/example.svg',
],
];
12. INCLUDE_TYPOSCRIPT Syntax
The <INCLUDE_TYPOSCRIPT:> syntax is deprecated.
Before v13
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:my_extension/Configuration/TypoScript/myMenu.typoscript">
After v13
@import 'EXT:my_extension/Configuration/TypoScript/myMenu.typoscript'
13. Plugin Content Element and SubTypes
Registering plugins via list_type is deprecated.
TYPO3 v14 approach:
Each plugin must have its own CType.
14. @typo3/backend/wizard.js
The legacy wizard module is deprecated.
Replacement:
@typo3/backend/multi-step-wizard.js
Required for backend wizard extensions.
Before v13
import Wizard from '@typo3/backend/wizard.js';
Wizard.addSlide(
'My-slide-identifier',
'Slide title',
'Content of my slide',
SeverityEnum.notice,
function () {
// callback executed after displaying the slide
}
);
After
import MultiStepWizard from '@typo3/backend/multi-step-wizard.js';
MultiStepWizard.addSlide(
'my-slide-identifier',
'Slide title',
'Content of my slide',
SeverityEnum.notice,
'My step',
function () {
// callback executed after displaying the slide
}
);
15. Page Tree Navigation Component ID
The page tree component ID has been renamed.
Old:
@typo3/backend/page-tree/page-tree-element
New:
@typo3/backend/tree/page-tree-element
Update custom backend modules accordingly.
16. GeneralUtility::hmac()
GeneralUtility::hmac() is deprecated.
Replacement:
HashService::hmac()
Use dependency injection or GeneralUtility::makeInstance().
Before v13
$hmac = GeneralUtility::hmac('some-input', 'some-secret');
After v13
use TYPO3\CMS\Core\Crypto\HashService;
$hashService = GeneralUtility::makeInstance(HashService::class);$hmac = $hashService->hmac('some-input', 'some-secret');
17. Fluid Variables: true, false, null
Fluid no longer allows variables named true, false, or null.
Action:
Rename conflicting variables to avoid runtime exceptions.
Before v13
<f:variable name="true" value="someValue" />
After v13
<f:variable name="myTrue" value="someValue" />
How to Handle Deprecations in Practice
- Do not block your v13 upgrade for deprecations alone
- Fix deprecations in actively maintained extensions
- Remove deprecated APIs in custom code you control
- Leave third-party extensions for vendor updates if needed
Addressing these early will significantly reduce effort when moving to TYPO3 v14.
Practical Upgrade Checklist for Your Project
Use this as a final check before and after your v13 upgrade.
Before the Upgrade
- Review and fix breaking changes in custom code
- Replace removed hooks with PSR-14 events
- Check extensions for v13 compatibility
- Resolve all deprecations reported in v12
During the Upgrade
- Run all Upgrade Wizards in the Install Tool
- Validate database schema and TCA changes
- Clear caches and confirm backend access
After the Upgrade
- Test backend workflows, RTE, and custom modules
- Verify frontend rendering and critical user flows
- Search the codebase for deprecated APIs and constants
- Monitor logs for remaining warnings or notices
Projects that treat these steps as mandatory, not optional, avoid most upgrade regressions and reduce long-term maintenance risk.
Conclusion
TYPO3 v13 tightens the platform in the right places. Legacy hooks are gone, APIs are clearer, and dependencies are modern. The upgrade is manageable if handled methodically.
Projects that address breaking changes early and clean up deprecations now will move into TYPO3 v14 with far less effort.
FAQs
Yes. TYPO3 v14 removes APIs and patterns that are only deprecated in v13. Skipping v13 means dealing with breaking changes and deprecations at the same time, which significantly increases upgrade risk. A clean v13 upgrade reduces effort and makes the v14 transition predictable.
Custom extensions are the most common failure point. Removed hooks, QueryBuilder API changes, stricter typing in Extbase, and deprecated access to $GLOBALS['TSFE'] often cause fatal errors. Core-only projects with minimal customization usually upgrade with fewer issues.
Yes, but it is not recommended. Deprecations do not block TYPO3 v13, but leaving them unresolved increases technical debt and makes the v14 upgrade harder. Deprecations in actively maintained extensions should be fixed during the v13 upgrade cycle.
Extensions should be audited first. TYPO3 upgrades are often blocked by incompatible extensions, not core changes. Fix or replace unsupported extensions before refactoring custom code. Custom extensions usually require more work than site packages or templates.
It depends on project complexity. Simple projects may upgrade in a few days. Projects with multiple custom extensions and legacy hooks often require several weeks, including testing and cleanup. Planning and extension audits have more impact than raw development speed.
Treating deprecations as optional and postponing architectural fixes. Legacy hooks, loose typing, and outdated APIs may still work in v13 but will fail in v14. Fixing them early reduces long-term maintenance cost and avoids rushed upgrades later.

Wolfgang Weber
Brand & Communication LeadWolfgang Weber shapes TYPO3 with passion and expertise. As TYPO3 enthusiast, he has contributed to TYPO3 projects that make websites faster and more secure. Outside of TYPO3, you'll probably find him exploring local cafés and…
More From Author