diff --git a/typo3/sysext/backend/Classes/Controller/BackendController.php b/typo3/sysext/backend/Classes/Controller/BackendController.php
index f7c3472b5fcf63dc00a3e1201c43ec9a9d0b33a6..2d51a0066bbfead2aee5ec2c3d8b9933ecd77096 100644
--- a/typo3/sysext/backend/Classes/Controller/BackendController.php
+++ b/typo3/sysext/backend/Classes/Controller/BackendController.php
@@ -17,8 +17,10 @@ declare(strict_types=1);
 
 namespace TYPO3\CMS\Backend\Controller;
 
+use Psr\EventDispatcher\EventDispatcherInterface;
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Backend\Controller\Event\AfterBackendPageRenderEvent;
 use TYPO3\CMS\Backend\Module\MenuModule;
 use TYPO3\CMS\Backend\Module\ModuleInterface;
 use TYPO3\CMS\Backend\Module\ModuleProvider;
@@ -50,8 +52,6 @@ class BackendController
 {
     use PageRendererBackendSetupTrait;
 
-    protected string $css = '';
-
     /**
      * @var ModuleInterface[]
      */
@@ -65,9 +65,8 @@ class BackendController
         protected readonly ToolbarItemsRegistry $toolbarItemsRegistry,
         protected readonly ExtensionConfiguration $extensionConfiguration,
         protected readonly BackendViewFactory $viewFactory,
+        protected readonly EventDispatcherInterface $eventDispatcher,
     ) {
-        // @todo: This hook is essentially useless.
-        $this->executeHook('constructPostProcess');
         $this->modules = $this->moduleProvider->getModulesForModuleMenu($this->getBackendUser());
     }
 
@@ -79,8 +78,6 @@ class BackendController
         $backendUser = $this->getBackendUser();
         $pageRenderer = $this->pageRenderer;
 
-        $this->executeHook('renderPreProcess');
-
         $this->setUpBasicPageRendererForBackend($pageRenderer, $this->extensionConfiguration, $request, $this->getLanguageService());
 
         $javaScriptRenderer = $pageRenderer->getJavaScriptRenderer();
@@ -131,7 +128,6 @@ class BackendController
         $dateFormat = ['DD-MM-Y', 'HH:mm DD-MM-Y'];
         // Needed for FormEngine manipulation (date picker)
         $pageRenderer->addInlineSetting('DateTimePicker', 'DateFormat', $dateFormat);
-        $pageRenderer->addCssInlineBlock('BackendInlineCSS', $this->css);
         $typo3Version = 'TYPO3 CMS ' . $this->typo3Version->getVersion();
         $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . ' [' . $typo3Version . ']' : $typo3Version;
         $pageRenderer->setTitle($title);
@@ -148,7 +144,7 @@ class BackendController
             'sitenameFirstInBackendTitle' => ($backendUser->uc['backendTitleFormat'] ?? '') === 'sitenameFirst',
         ]);
         $content = $view->render('Backend/Main');
-        $this->executeHook('renderPostProcess', ['content' => &$content]);
+        $content = $this->eventDispatcher->dispatch(new AfterBackendPageRenderEvent($content, $view))->getContent();
         $bodyTag = '<body class="scaffold t3js-scaffold' . (!$moduleMenuCollapsed && $this->modules ? ' scaffold-modulemenu-expanded' : '') . '">';
         $pageRenderer->addBodyContent($bodyTag . $content);
         return $pageRenderer->renderResponse();
@@ -177,16 +173,6 @@ class BackendController
         return new JsonResponse(['topbar' => $view->render('Backend/Topbar')]);
     }
 
-    /**
-     * Adds a css snippet to the backend. This method is old and its purpose
-     * seems to be that hooks (see executeHook()) can add css?
-     * @todo: Candidate for deprecation / removal.
-     */
-    public function addCss(string $css): void
-    {
-        $this->css .= $css;
-    }
-
     /**
      * Renders the topbar, containing the backend logo, sitename etc.
      */
@@ -365,22 +351,6 @@ class BackendController
         return $modules;
     }
 
-    /**
-     * Executes defined hooks functions for the given identifier.
-     *
-     * These hook identifiers are valid:
-     * + constructPostProcess
-     * + renderPreProcess
-     * + renderPostProcess
-     */
-    protected function executeHook(string $identifier, array $hookConfiguration = []): void
-    {
-        $options = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php'];
-        foreach ($options[$identifier] ?? [] as $hookFunction) {
-            GeneralUtility::callUserFunction($hookFunction, $hookConfiguration, $this);
-        }
-    }
-
     protected function getCollapseStateOfMenu(): bool
     {
         $backendUser = $this->getBackendUser();
diff --git a/typo3/sysext/backend/Classes/Controller/Event/AfterBackendPageRenderEvent.php b/typo3/sysext/backend/Classes/Controller/Event/AfterBackendPageRenderEvent.php
new file mode 100644
index 0000000000000000000000000000000000000000..c4c3aa531a90df3687ce21be17135b11ee044a10
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Controller/Event/AfterBackendPageRenderEvent.php
@@ -0,0 +1,48 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Backend\Controller\Event;
+
+use TYPO3\CMS\Core\View\ViewInterface;
+
+/**
+ * This event triggers after a page has been rendered.
+ *
+ * Listeners may update the page content string with a modified
+ * version if appropriate.
+ */
+final class AfterBackendPageRenderEvent
+{
+    public function __construct(private string $content, private readonly ViewInterface $view)
+    {
+    }
+
+    public function getContent(): string
+    {
+        return $this->content;
+    }
+
+    public function setContent(string $content): void
+    {
+        $this->content = $content;
+    }
+
+    public function getView(): ViewInterface
+    {
+        return $this->view;
+    }
+}
diff --git a/typo3/sysext/backend/Tests/Functional/Controller/BackendControllerTest.php b/typo3/sysext/backend/Tests/Functional/Controller/BackendControllerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2bf63e6622b0db91838a81b21767cd6007116ddf
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Functional/Controller/BackendControllerTest.php
@@ -0,0 +1,72 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Backend\Tests\Functional\Controller;
+
+use Symfony\Component\DependencyInjection\Container;
+use TYPO3\CMS\Backend\Controller\BackendController;
+use TYPO3\CMS\Backend\Controller\Event\AfterBackendPageRenderEvent;
+use TYPO3\CMS\Backend\Routing\Route;
+use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Core\SystemEnvironmentBuilder;
+use TYPO3\CMS\Core\EventDispatcher\ListenerProvider;
+use TYPO3\CMS\Core\Http\ServerRequest;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
+
+class BackendControllerTest extends FunctionalTestCase
+{
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->setUpBackendUserFromFixture(1);
+        Bootstrap::initializeLanguageObject();
+    }
+
+    /**
+     * @test
+     */
+    public function backendPageRenderEventIsTriggered(): void
+    {
+        /** @var Container $container */
+        $container = $this->getContainer();
+
+        $state = [
+            'after-backend-page-render-listener' => null,
+        ];
+
+        // Dummy listeners that just record that the event existed.
+        $container->set(
+            'after-backend-page-render-listener',
+            static function (AfterBackendPageRenderEvent $event) use (&$state) {
+                $state['after-backend-page-render-listener'] = $event;
+            }
+        );
+
+        $eventListener = GeneralUtility::makeInstance(ListenerProvider::class);
+        $eventListener->addListener(AfterBackendPageRenderEvent::class, 'after-backend-page-render-listener');
+
+        $request = (new ServerRequest())
+            ->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_BE)
+            ->withAttribute('route', new Route('/main', ['packageName' => 'typo3/cms-backend', '_identifier' => 'main']));
+
+        $subject = $this->get(BackendController::class);
+        $subject->mainAction($request);
+
+        self::assertInstanceOf(AfterBackendPageRenderEvent::class, $state['after-backend-page-render-listener']);
+    }
+}
diff --git a/typo3/sysext/core/Documentation/Changelog/12.0/Breaking-97451-RemoveBackendControllerPageHooks.rst b/typo3/sysext/core/Documentation/Changelog/12.0/Breaking-97451-RemoveBackendControllerPageHooks.rst
new file mode 100644
index 0000000000000000000000000000000000000000..9459245d7ae881425ad5d08bcd4ae956e2af74fa
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/12.0/Breaking-97451-RemoveBackendControllerPageHooks.rst
@@ -0,0 +1,40 @@
+.. include:: /Includes.rst.txt
+
+=======================================================
+Breaking: #97451 - Removed BackendController page hooks
+=======================================================
+
+See :issue:`97451`
+
+Description
+===========
+
+The hooks :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['constructorPostProcess']`,
+:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['renderPreProcess']`, and
+:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['renderPostProcess']` have
+been removed in favor of a new PSR-14 Event :php:`\TYPO3\CMS\Backend\Controller\Event\AfterBackendPageRenderEvent`.
+
+Additionally, the :php:`BackendController->addCss()` method has been removed without replacement,
+as it is no longer used.
+
+Impact
+======
+
+Any hook implementation registered is not executed anymore in
+TYPO3 v12.0+. The extension scanner will report possible usages.
+
+Affected Installations
+======================
+
+All TYPO3 installations using this hook in custom extension code.
+
+Migration
+=========
+
+The hooks are removed without deprecation in order to allow extensions
+to work with TYPO3 v11 (using the hook) and v12+ (using the new Event)
+when implementing the Event as well without any further deprecations.
+Use the :doc:`PSR-14 Event <../12.0/Feature-97451-PSR-14EventsForBackendPageController>`
+as an improved replacement.
+
+.. index:: Backend, PHP-API, FullyScanned, ext:backend
diff --git a/typo3/sysext/core/Documentation/Changelog/12.0/Feature-97451-PSR-14EventsForBackendPageController.rst b/typo3/sysext/core/Documentation/Changelog/12.0/Feature-97451-PSR-14EventsForBackendPageController.rst
new file mode 100644
index 0000000000000000000000000000000000000000..addd0e3cd1b2d8b005c4bd9a503d69f7d2dbea78
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/12.0/Feature-97451-PSR-14EventsForBackendPageController.rst
@@ -0,0 +1,53 @@
+.. include:: /Includes.rst.txt
+
+==================================================================
+Feature: #97451 - PSR-14 Events for modifying backend page content
+==================================================================
+
+See :issue:`97451`
+
+Description
+===========
+A new PSR-14 Event :php:`\TYPO3\CMS\Backend\Controller\Event\AfterBackendPageRenderEvent` has
+been introduced which serves as a direct replacement for the now removed
+:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['constructorPostProcess']`,
+:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['renderPreProcess']`, and
+:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['renderPostProcess']`
+:doc:`hooks <../12.0/Breaking-97451-RemoveBackendControllerPageHooks>`.
+
+The new Event triggers after the page is rendered and includes
+the rendered page body. Listeners may overwrite the page string if desired.
+
+Example
+=======
+
+Registration of the Event in your extension's :file:`Services.yaml`:
+
+.. code-block:: yaml
+
+    MyVendor\MyPackage\MyEventListener:
+      tags:
+        - name: event.listener
+          identifier: 'my-package/backend/after-backend-controller-render'
+
+The corresponding event listener class:
+
+.. code-block:: php
+
+    use TYPO3\CMS\Backend\Controller\Event\AfterBackendPageRenderEvent;
+
+    final class MyEventListener
+    {
+        public function __invoke(AfterBackendPageRenderEvent $event): void
+        {
+            $content = $event->getContent() . ' I was here';
+            $event->setContent($content);
+        }
+    }
+
+Impact
+======
+
+It's now possible to modify the backend page using the new PSR-14 :php:`AfterBackendPageRenderEvent`.
+
+.. index:: Backend, PHP-API, ext:backend
diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/ArrayDimensionMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/ArrayDimensionMatcher.php
index 7598197321deec04b29de543c18771a6286f94c0..7abd32237386fb2eb03bbde140d74a750a2e48be 100644
--- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/ArrayDimensionMatcher.php
+++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/ArrayDimensionMatcher.php
@@ -784,4 +784,22 @@ return [
             'Feature-97862-NewPSR-14EventsForManipulatingFrontendPageGenerationAndCacheBehaviour.rst',
         ],
     ],
+    '$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'typo3/backend.php\'][\'constructorPostProcess\']' => [
+        'restFiles' => [
+            'Breaking-97451-RemoveBackendControllerPageHooks.rst',
+            'Feature-97451-PSR-14EventsForBackendPageController.rst',
+        ],
+    ],
+    '$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'typo3/backend.php\'][\'renderPreProcess\']' => [
+        'restFiles' => [
+            'Breaking-97451-RemoveBackendControllerPageHooks.rst',
+            'Feature-97451-PSR-14EventsForBackendPageController.rst',
+        ],
+    ],
+    '$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'typo3/backend.php\'][\'renderPostProcess\']' => [
+        'restFiles' => [
+            'Breaking-97451-RemoveBackendControllerPageHooks.rst',
+            'Feature-97451-PSR-14EventsForBackendPageController.rst',
+        ],
+    ],
 ];
diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php
index d22e0374c2c2bb400825861733dec537aa1153aa..cbcb02cbd8806078769f68dce1585b36cdc4d668 100644
--- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php
+++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php
@@ -5323,4 +5323,11 @@ return [
             'Deprecation-97531-ContextRelatedMethodsWithinTSFE.rst',
         ],
     ],
+    'TYPO3\CMS\Backend\Controller\BackendController->addCss' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Breaking-97451-RemoveBackendControllerPageHooks.rst',
+        ],
+    ],
 ];