---
title: How to set up RabbitMQ as a message queue for TYPO3 with DDEV
url: "https://b13.com/knowledge/better-scalability-with-decoupled-queues-how-to-set-up-rabbitmq-with-typo3"
description: When built-in message transports hit their limits, RabbitMQ can provide TYPO3 with a scalable, robust message queue.
image: "https://b13.com/fileadmin/_processed_/7/3/csm_QueuesDDEV_Sharing_ca74d06702.png"
date: 2024-03-27
modified: 2026-08-19
lastUpdated: 2026-08-19
---

# How to set up RabbitMQ as a message queue for TYPO3 with DDEV

[ DDEV ](https://b13.com/knowledge/ddev) [ TYPO3 ](https://b13.com/knowledge/typo3)

 Better scalability with decoupled queues: How to set up RabbitMQ with TYPO3
=============================================================================

![](https://b13.com/fileadmin/_processed_/d/d/csm_jochen_7e22d3ed81.jpg)Jochen Roth

  10 April 2024  | Updated 04 May 2026

 [ RSS Feed ](https://b13.com/rss.xml)

  ![A series of stylized figures in various poses, each with a distinctive orange hat, depict a progression from walking to standing still while looking at a phone, set against a purple grid background.](https://b13.com/fileadmin/_processed_/d/7/csm_QueuesDDEV_Headerbild_86b0cc20d5.webp)

TYPO3 [v12](https://typo3.org/article/typo3-v12-lts-here-to-save-the-day) supports [Symfony Messenger](https://symfony.com/doc/current/messenger.html), a flexible message bus with the ability to send messages inside the application for immediate handling or through external message transport services for asynchronous handling.

In this article, we go through the steps of adding an external transport, [RabbitMQ](https://www.rabbitmq.com/), to a TYPO3 instance.

   Understanding external messaging services
-------------------------------------------

[Symfony Messenger](https://symfony.com/doc/current/messenger.html) supports a number of different transport types, including:

- In-memory
- Doctrine
- Redis
- AMQP
- and more.

Typically, you will want to start with the most straightforward options. The in-memory transport is perhaps the simplest one but is mainly used for testing purposes.

The Doctrine transport uses the existing database to store messages. It is often the transport of choice because it is easy to set up and requires no external dependencies.

However, Doctrine shouldn’t be your ultimate solution because using a database as a message queue does not scale well. At some point, you’ll want to use an external message queue system such as RabbitMQ or Redis—intermediaries that give your applications, microservices, and software components a common platform to exchange messages.

In this article, we focus on [RabbitMQ](https://www.rabbitmq.com/), a very popular and mature open-source messaging broker.

Over and above the Doctrine transport built-in to TYPO3, a system like RabbitMQ has several advantages:

- **It scales well.** RabbitMQ can serve large numbers of message providers and consumers. Applications can connect to each other, as components of a larger application, or to user devices and data. The workload can be distributed across multiple processes.
- **Support for distributed systems.** RabbitMQ can run message brokers on multiple nodes to distribute workload to a network of services and route messages between producers and consumers.
- **Fault-tolerant by design.** Messages are stored in a queue until they get consumed. The queue can absorb load spikes and store messages in case one or more consumers are temporarily unavailable.

Those advantages make it worth investing time to set up an external message transport for TYPO3. If you want to try out RabbitMQ, read on to see how to create a DDEV-based message queue project.

   How to set up RabbitMQ in TYPO3 with DDEV
-------------------------------------------

Let’s start from a blank slate. For this exercise, we’re going to use [Docker](https://docker.com) and [DDEV](https://ddev.com/), and the [GitLab TYPO3 site package](https://gitlab.com/gitlab-org/project-templates/typo3-distribution), so you’ll need a GitLab account. The GitLab TYPO3 site package is a project template ready for building a [site package](https://docs.typo3.org/m/typo3/tutorial-sitepackage/12.4/en-us/Index.html#start) on top of a clean TYPO3 installation.

### Install Docker and DDEV

DDEV manages containerized PHP development environments and lets you set up a project in seconds.

Follow the [DDEV installation instructions](https://ddev.com/get-started/) to install both Docker and DDEV.

For the setup also see the [documentation on DDEV](https://ddev.readthedocs.io/en/stable/users/extend/customizing-images/#adding-extra-debian-packages-with-webimage_extra_packages-and-dbimage_extra_packages).

### Set up a TYPO3 Site

The TYPO3 Distribution template in GitLab is an easy way of setting up a TYPO3 site including a blank site package.

1\. Log in to GitLab

2\. In the top-left corner, click the plus **+** button and select **New project/repository**.

  ![Menu options for creating new items in a software interface, including "New project/repository," "New group," and "New snippet," displayed alongside a logo in the top left corner.](https://b13.com/fileadmin/_processed_/2/6/csm_Setup_RabbitMQ_2fcce1895e.webp)

  3\. Select **Create from template**.

4\. In the list of templates, scroll down to “TYPO3 Distribution” then click **Use template**.

  ![TYPO3 Distribution template for initiating a new TYPO3 project, featuring options to preview or use the template.](https://b13.com/fileadmin/_processed_/7/5/csm_Setup_RabbitMQ_1_b2fc2476a6.webp)

  5\. In the template form, enter the name “TYPO3 and RabbitMQ”. Choose a group or namespace, then click **Create project**.

  ![Form fields for creating a project titled "TYPO3 and RabbitMQ," including inputs for project name, URL, slug, description, and visibility level options.](https://b13.com/fileadmin/_processed_/7/4/csm_Setup_RabbitMQ_2_cd9017a107.webp)

  6\. When the project is created, open a local shell on your system and clone the repository to a local folder.

7\. CD into the project and initialize TYPO3.

  ```
1<br></br>2<br></br>3<br></br>
```

```
<span class="hljs-attr">cd</span> <span class="hljs-string">typo3-and-rabbitmq</span><span class="hljs-attr"><br></br></span><br></br><span class="hljs-attr">ddev</span> <span class="hljs-string">typo3-init</span><br></br>
```

  This command builds the initial project and starts Docker containers with a Web server and a database inside.

When the command is finished, it prints the login credentials to the terminal and opens the login page in the browser.

8\. Log in to test that TYPO3 runs fine. If the login page does not open automatically, open it at the path /TYPO3. Based on the GitLab details from step 5, the login URL would be “https://typo3-and-rabbitmq.ddev.site/typo3”.

  ### Install RabbitMQ

Now you can install RabbitMQ via DDEV.

1.In the shell, run

  ```
1<br></br>
```

```
ddev <span class="hljs-builtin-name">get</span> b13/ddev-rabbitmq<br></br>
```

  2\. Add these lines to your **.ddev/config.yaml**:

  ```
1<br></br>
```

```
webimage_extra_packages: [<span class="hljs-string">"php${DDEV_PHP_VERSION}-amqp"</span>]<br></br>
```

  AMQP is the message protocol that RabbitMQ uses. The webimage\_extra\_packages ensures that the amqp package is installed.

3\. Now restart your containers to apply the change:

  ```
1<br></br>
```

```
<span class="hljs-attribute">ddev restart</span><br></br>
```

  This may take a few seconds.

4\. Run ddev describe to see if RabbitMQ is installed. The command reveals the URL of the RabbitMQ service.

### Install AMQP support for the Symfony Messenger

RabbitMQ uses the AMPQ protocol, so we move on to setting up AMQP for the Symfony Messenger.

1\. Install the symfony/messenger package:

  ```
1<br></br>
```

```
ddev composer req symfony/amqp-messenger:^<span class="hljs-number">6.4</span><br></br>
```

  2\. TYPO3 needs to know how to talk to the RabbitMQ service. To achieve this, edit the file in **packages/site-distribution/Configuration/Services.yaml** as follows (make sure you preserve the indentation):

  ```
1<br></br>2<br></br>3<br></br>4<br></br>5<br></br>6<br></br>7<br></br>8<br></br>9<br></br>10<br></br>11<br></br>12<br></br>13<br></br>14<br></br>15<br></br>16<br></br>17<br></br>18<br></br>19<br></br>20<br></br>21<br></br>22<br></br>23<br></br>24<br></br>25<br></br>26<br></br>27<br></br>28<br></br>29<br></br>30<br></br>31<br></br>32<br></br>33<br></br>34<br></br>35<br></br>36<br></br>37<br></br>
```

```
services:<br></br>  _defaults:<br></br>    autowire: true<br></br>    autoconfigure: true<br></br>    public: true<br></br><br></br>  Site<span class="hljs-tag">\<span class="hljs-name">Distribution</span></span><span class="hljs-tag">\<span class="hljs-name">:</span></span><br></br>    resource: "../Classes/*"<br></br>    exclude: "../Classes/Domain/Model/*"<br></br><br></br>  Site<span class="hljs-tag">\<span class="hljs-name">Distribution</span></span><span class="hljs-tag">\<span class="hljs-name">Queue</span></span><span class="hljs-tag">\<span class="hljs-name">Handler</span></span><span class="hljs-tag">\<span class="hljs-name">MyHandler</span></span>:<br></br>    tags:<br></br>      - name: "messenger.message_handler"<br></br><br></br>  Site<span class="hljs-tag">\<span class="hljs-name">Distribution</span></span><span class="hljs-tag">\<span class="hljs-name">Queue</span></span><span class="hljs-tag">\<span class="hljs-name">Message</span></span><span class="hljs-tag">\<span class="hljs-name">MyMessage</span></span>:<br></br>    arguments:<br></br>      <span class="hljs-formula">$content: 'Default content'<br></br><br></br>  # RabbitMQ<br></br>  Symfony<span class="hljs-tag">\<span class="hljs-name">Component</span></span><span class="hljs-tag">\<span class="hljs-name">Messenger</span></span><span class="hljs-tag">\<span class="hljs-name">Bridge</span></span><span class="hljs-tag">\<span class="hljs-name">Amqp</span></span><span class="hljs-tag">\<span class="hljs-name">Transport</span></span><span class="hljs-tag">\<span class="hljs-name">AmqpTransportFactory</span></span>:<br></br>    public: true<br></br><br></br>  Symfony<span class="hljs-tag">\<span class="hljs-name">Component</span></span><span class="hljs-tag">\<span class="hljs-name">Messenger</span></span><span class="hljs-tag">\<span class="hljs-name">Bridge</span></span><span class="hljs-tag">\<span class="hljs-name">Amqp</span></span><span class="hljs-tag">\<span class="hljs-name">Transport</span></span><span class="hljs-tag">\<span class="hljs-name">AmqpTransport</span></span>:<br></br>    factory:<br></br>      [<br></br>        '@Symfony<span class="hljs-tag">\<span class="hljs-name">Component</span></span><span class="hljs-tag">\<span class="hljs-name">Messenger</span></span><span class="hljs-tag">\<span class="hljs-name">Bridge</span></span><span class="hljs-tag">\<span class="hljs-name">Amqp</span></span><span class="hljs-tag">\<span class="hljs-name">Transport</span></span><span class="hljs-tag">\<span class="hljs-name">AmqpTransportFactory</span></span>',<br></br>        "createTransport",<br></br>      ]<br></br>    arguments:<br></br>      $</span>dsn: "amqp://rabbitmq:rabbitmq@rabbitmq:5672/<span class="hljs-comment">%2f/queue"</span><br></br>      <span class="hljs-formula">$options: {}<br></br>    tags:<br></br>      - name: "messenger.sender"<br></br>        identifier: "amqp"<br></br>      - name: "messenger.receiver"<br></br>        identifier: "amqp"<br></br></span><br></br>
```

  Note the $dsn argument that holds the connection string. When deploying to production, you will want to adjust its parameters accordingly. This is the canonical form of the AMQP DSN:

  ```
1<br></br>
```

```
amqp://<span class="hljs-tag"><<span class="hljs-name">username</span>></span>:<span class="hljs-tag"><<span class="hljs-name">password</span>></span>@rabbitmq:5672/<span class="hljs-tag"><<span class="hljs-name">virtual</span> <span class="hljs-attr">host</span>></span>/<span class="hljs-tag"><<span class="hljs-name">queue</span> <span class="hljs-attr">name</span>></span><br></br>
```

  ### Create a message class

For dispatching and processing a message, you need a message class. A very simple version of a message class is the following, which you can create in **Classes/Queue/Message/MyMessage.php:**

  ```
1<br></br>2<br></br>3<br></br>4<br></br>5<br></br>6<br></br>7<br></br>8<br></br>9<br></br>10<br></br>11<br></br>12<br></br>13<br></br>
```

```
<span class="php"><span class="hljs-meta"><?php</span><br></br><br></br><span class="hljs-keyword">declare</span>(strict_types=<span class="hljs-number">1</span>);<br></br><br></br><span class="hljs-keyword">namespace</span> <span class="hljs-title">Site</span>\<span class="hljs-title">Distribution</span>\<span class="hljs-title">Queue</span>\<span class="hljs-title">Message</span>;<br></br><br></br><span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyMessage</span><br></br></span>{<br></br>	<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span><span class="hljs-params">(<br></br>    	public readonly string $content<br></br>	)</span> </span>{<br></br>	}<br></br>}</span><br></br>
```

  3\. The MyMessage class needs to be wired to asynchronous transport via AMQP. Edit the **packages/site-distribution/ext\_localconf.php** file accordingly:

  ```
1<br></br>2<br></br>3<br></br>4<br></br>5<br></br>6<br></br>7<br></br>8<br></br>9<br></br>10<br></br>11<br></br>12<br></br>13<br></br>14<br></br>15<br></br>16<br></br>17<br></br>18<br></br>19<br></br>20<br></br>21<br></br>22<br></br>23<br></br>24<br></br>25<br></br>26<br></br>
```

```
<span class="php"><span class="hljs-meta"><?php</span><br></br><br></br><span class="hljs-keyword">declare</span>(strict_types=<span class="hljs-number">1</span>);<br></br><br></br><span class="hljs-keyword">use</span> <span class="hljs-title">Site</span>\<span class="hljs-title">Distribution</span>\<span class="hljs-title">Queue</span>\<span class="hljs-title">Message</span>\<span class="hljs-title">MyMessage</span>;<br></br><span class="hljs-keyword">use</span> <span class="hljs-title">TYPO3</span>\<span class="hljs-title">CMS</span>\<span class="hljs-title">Core</span>\<span class="hljs-title">Messaging</span>\<span class="hljs-title">WebhookMessageInterface</span>;<br></br><br></br>defined(<span class="hljs-string">'TYPO3'</span>) <span class="hljs-keyword">or</span> <span class="hljs-keyword">die</span>();<br></br><br></br><span class="hljs-comment">// Include vite generated manifest file (global)</span><br></br>$GLOBALS[<span class="hljs-string">'TYPO3_CONF_VARS'</span>][<span class="hljs-string">'EXTENSIONS'</span>][<span class="hljs-string">'vite_asset_collector'</span>][<span class="hljs-string">'defaultManifest'</span>] = <span class="hljs-string">'EXT:site-distribution/Resources/Public/Vite/.vite/manifest.json'</span>;<br></br><br></br><span class="hljs-comment">// Include custom RTE config</span><br></br>$GLOBALS[<span class="hljs-string">'TYPO3_CONF_VARS'</span>][<span class="hljs-string">'RTE'</span>][<span class="hljs-string">'Presets'</span>][<span class="hljs-string">'default'</span>] = <span class="hljs-string">'EXT:site-distribution/Configuration/RTE/RteDefaultPreset.yaml'</span>;<br></br><br></br><span class="hljs-comment">// Unset the default, so that it no longer applies</span><br></br><span class="hljs-keyword">unset</span>($GLOBALS[<span class="hljs-string">'TYPO3_CONF_VARS'</span>][<span class="hljs-string">'SYS'</span>][<span class="hljs-string">'messenger'</span>][<span class="hljs-string">'routing'</span>][<span class="hljs-string">'*'</span>]);<br></br><br></br><span class="hljs-comment">// Set Webhook-Messages and MyMessage to asynchronous transport via amqp</span><br></br><span class="hljs-keyword">foreach</span> ([WebhookMessageInterface::class, MyMessage::class] <span class="hljs-keyword">as</span> $className) {<br></br>    $GLOBALS[<span class="hljs-string">'TYPO3_CONF_VARS'</span>][<span class="hljs-string">'SYS'</span>][<span class="hljs-string">'messenger'</span>][<span class="hljs-string">'routing'</span>][$className] = <span class="hljs-string">'amqp'</span>;<br></br>}<br></br><br></br>$GLOBALS[<span class="hljs-string">'TYPO3_CONF_VARS'</span>][<span class="hljs-string">'SYS'</span>][<span class="hljs-string">'messenger'</span>][<span class="hljs-string">'config'</span>][<span class="hljs-string">'amqp'</span>] = [<br></br>    <span class="hljs-string">'dsn'</span> => <span class="hljs-string">'amqp://rabbitmq:rabbitmq@rabbitmq:5672/%2f/messages'</span>,<br></br>];</span><br></br>
```

  ### Set up a message handler class

A message handler receives and processes messages from the RabbitMQ broker. It does not actively reach out to the broker but rather relies on a consumer process that reads each message and passes it to the message handler.

Here is a simple version of a message handler that you can create in **packages/site-distribution/Classes/Queue/Handler/MyHandler.php**:

  ```
1<br></br>2<br></br>3<br></br>4<br></br>5<br></br>6<br></br>7<br></br>8<br></br>9<br></br>10<br></br>11<br></br>12<br></br>13<br></br>14<br></br>15<br></br>16<br></br>17<br></br>18<br></br>19<br></br>20<br></br>21<br></br>22<br></br>23<br></br>24<br></br>25<br></br>26<br></br>27<br></br>28<br></br>29<br></br>30<br></br>
```

```
<span class="php"><span class="hljs-meta"><?php</span><br></br><br></br><span class="hljs-keyword">declare</span>(strict_types=<span class="hljs-number">1</span>);<br></br><br></br><span class="hljs-keyword">namespace</span> <span class="hljs-title">Site</span>\<span class="hljs-title">Distribution</span>\<span class="hljs-title">Queue</span>\<span class="hljs-title">Handler</span>;<br></br><br></br><span class="hljs-keyword">use</span> <span class="hljs-title">Site</span>\<span class="hljs-title">Distribution</span>\<span class="hljs-title">Queue</span>\<span class="hljs-title">Message</span>\<span class="hljs-title">MyMessage</span>;<br></br><span class="hljs-keyword">use</span> <span class="hljs-title">Symfony</span>\<span class="hljs-title">Component</span>\<span class="hljs-title">Messenger</span>\<span class="hljs-title">Envelope</span>;<br></br><span class="hljs-keyword">use</span> <span class="hljs-title">Symfony</span>\<span class="hljs-title">Component</span>\<span class="hljs-title">Messenger</span>\<span class="hljs-title">MessageBusInterface</span>;<br></br><span class="hljs-keyword">use</span> <span class="hljs-title">Symfony</span>\<span class="hljs-title">Component</span>\<span class="hljs-title">Messenger</span>\<span class="hljs-title">Stamp</span>\<span class="hljs-title">DelayStamp</span>;<br></br><br></br><span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHandler</span><br></br></span>{<br></br>	<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span><span class="hljs-params">(private readonly MessageBusInterface $bus)</span><br></br>	</span>{<br></br>	}<br></br><br></br>	<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__invoke</span><span class="hljs-params">(MyMessage $message)</span>: <span class="hljs-title">void</span><br></br>	</span>{<br></br>		<span class="hljs-keyword">try</span> {<br></br><br></br>			<span class="hljs-comment">// Process $message</span><br></br><br></br>		} <span class="hljs-keyword">catch</span> (\<span class="hljs-keyword">Exception</span> $exception) {<br></br>			<span class="hljs-comment">// Workaround to support infinite retryable messages. So no message gets lost.</span><br></br>			$envelope = <span class="hljs-keyword">new</span> Envelope(<span class="hljs-keyword">new</span> MyMessage($message->content), [<span class="hljs-keyword">new</span> DelayStamp(<span class="hljs-number">5000</span>)]);<br></br>			<span class="hljs-keyword">$this</span>->bus->dispatch($envelope);<br></br>		}<br></br>	}<br></br>}</span><br></br>
```

  ### Test the message queue

Now it is time to test the queue. An easy way to feed messages into the queue is to set up a middleware that triggers on every page load.

1\. Add a class “RunTheRabbit” that implements the MiddlewareInterface to **packages/site-distribution/Classes/Middleware/RunTheRabbit.php:**

  ```
1<br></br>2<br></br>3<br></br>4<br></br>5<br></br>6<br></br>7<br></br>8<br></br>9<br></br>10<br></br>11<br></br>12<br></br>13<br></br>14<br></br>15<br></br>16<br></br>17<br></br>18<br></br>19<br></br>20<br></br>21<br></br>22<br></br>23<br></br>24<br></br>25<br></br>26<br></br>27<br></br>28<br></br>29<br></br>30<br></br>
```

```
<span class="php"><span class="hljs-meta"><?php</span><br></br><br></br><span class="hljs-keyword">declare</span>(strict_types=<span class="hljs-number">1</span>);<br></br><br></br><span class="hljs-keyword">namespace</span> <span class="hljs-title">Site</span>\<span class="hljs-title">Distribution</span>\<span class="hljs-title">Middleware</span>;<br></br><br></br><span class="hljs-keyword">use</span> <span class="hljs-title">Psr</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">Message</span>\<span class="hljs-title">ResponseInterface</span>;<br></br><span class="hljs-keyword">use</span> <span class="hljs-title">Psr</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">Message</span>\<span class="hljs-title">ServerRequestInterface</span>;<br></br><span class="hljs-keyword">use</span> <span class="hljs-title">Psr</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">Server</span>\<span class="hljs-title">MiddlewareInterface</span>;<br></br><span class="hljs-keyword">use</span> <span class="hljs-title">Psr</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">Server</span>\<span class="hljs-title">RequestHandlerInterface</span>;<br></br><span class="hljs-keyword">use</span> <span class="hljs-title">Site</span>\<span class="hljs-title">Distribution</span>\<span class="hljs-title">Queue</span>\<span class="hljs-title">Message</span>\<span class="hljs-title">MyMessage</span>;<br></br><span class="hljs-keyword">use</span> <span class="hljs-title">Symfony</span>\<span class="hljs-title">Component</span>\<span class="hljs-title">Messenger</span>\<span class="hljs-title">MessageBusInterface</span>;<br></br><br></br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RunTheRabbit</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">MiddlewareInterface</span><br></br></span>{<br></br>    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span><span class="hljs-params">(private readonly MessageBusInterface $bus)</span><br></br>    </span>{<br></br>    }<br></br><br></br>    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">process</span><span class="hljs-params">(<br></br>        ServerRequestInterface $request,<br></br>        RequestHandlerInterface $handler<br></br>    )</span>: <span class="hljs-title">ResponseInterface</span> </span>{<br></br>        $content = <span class="hljs-string">'Some important content'</span>;<br></br>        <span class="hljs-keyword">$this</span>->bus->dispatch(<span class="hljs-keyword">new</span> MyMessage($content));<br></br><br></br>        <span class="hljs-keyword">return</span> $handler->handle($request);<br></br>    }<br></br>}<br></br></span><br></br>
```

  2\. To register the middleware, create the file **packages/site-distribution/Configuration/RequestMiddlewares.php** and add the following code:

  ```
1<br></br>2<br></br>3<br></br>4<br></br>5<br></br>6<br></br>7<br></br>8<br></br>9<br></br>10<br></br>11<br></br>12<br></br>13<br></br>14<br></br>15<br></br>
```

```
<span class="php"><span class="hljs-meta"><?php</span><br></br><span class="hljs-keyword">return</span> [<br></br>    <span class="hljs-string">'frontend'</span> => [<br></br>        <span class="hljs-string">'site-rabbit'</span> => [<br></br>            <span class="hljs-string">'target'</span> => \Site\Distribution\Middleware\RunTheRabbit::class,<br></br>            <span class="hljs-string">'after'</span> => [<br></br>                <span class="hljs-string">'TYPO3/cms-frontend/authentication'</span>,<br></br>            ],<br></br>            <span class="hljs-string">'before'</span> => [<br></br>                <span class="hljs-string">'TYPO3/cms-frontend/base-redirect-resolver'</span>,<br></br>            ],<br></br>        ],<br></br>    ],<br></br>];<br></br></span><br></br>
```

  3\. It’s time to test! Restart TYPO3 to apply all changes:

  ```
1<br></br>
```

```
<span class="hljs-attribute">ddev restart</span><br></br>
```

  4\. Verify if all services are up and running:

  ```
1<br></br>
```

```
<span class="hljs-attribute">ddev describe</span><br></br>
```

  You should see an “OK” for the web, db, and rabbitmq services.

5\. You need to start a consumer to read the messages that RunTheRabbit sends to the queue. For ease of testing, you can use this one-liner:

  ```
1<br></br>
```

```
ddev <span class="hljs-type">TYPO3</span> messenger:<span class="hljs-keyword">consume</span> -vv amqp<br></br>
```

  The -vv flag causes the consumer to log its actions to the terminal.

6\. Now open the TYPO3 frontend. Every time you open or reload a page in the frontend, you will see this message in the terminal:

  ```
1<br></br>
```

```
[info] Site<span class="hljs-tag">\<span class="hljs-name">Distribution</span></span><span class="hljs-tag">\<span class="hljs-name">Queue</span></span><span class="hljs-tag">\<span class="hljs-name">Message</span></span><span class="hljs-tag">\<span class="hljs-name">MyMessage</span></span> was handled successfully (acknowledging to transport).<br></br>
```

  Congratulations! You have successfully set up RabbitMQ messaging with TYPO3.

Conclusion: Message queues and TYPO3 are a great team
-----------------------------------------------------

Setting up message queues with TYPO3 has become much more straightforward in v12. With a few steps, you were able to set up and integrate RabbitMQ with TYPO3. Now there are no more reasons to be worried about growing numbers of visitors at your site. If certain popular services, like PDF generation or zipping files for download, start consuming too much CPU power, you can outsource these tasks to asynchronous workers on different nodes, thanks to the new message queue integration.

  If you need help or services around implementing message queues, contact us!

 [ Get in touch. ](https://b13.com/lets-connect)

  ###  Written by:

 ![Bild von Jochen Roth](https://b13.com/fileadmin/_processed_/d/d/csm_jochen_88d69c78e9.webp)

Jochen is a community-oriented TYPO3 developer. He creates beautiful websites and loves a cleanly-written file of code. His essential tool: TYPO3.

 Jochen Roth  Development

 [ more from Jochen Roth ](https://b13.com/team/jochen-roth)

  Related Articles
------------------

- ![Cartoon trophy character surrounded by hands giving thumbs up and a heart gesture, set against a gear-patterned background.](https://b13.com/fileadmin/_processed_/f/7/csm_T3ppy_Design_Kit_Headerbild_b51eb9dc31.webp)

    ###  T3ppy Gives TYPO3 a Friendly Face

     06 August 2026 | Florian “Flix” Keitgen

     TYPO3 is powerful—but it doesn’t have to feel impersonal. Meet T3ppy, our friendly companion for the backend.

     [ Read more: T3ppy Gives TYPO3 a Friendly Face ](https://b13.com/knowledge/t3ppy-design-kit)
- ![Gavel labeled "AI" on a circuit-patterned background with yellow stars, symbolizing regulation or legislation related to artificial intelligence in the EU.](https://b13.com/fileadmin/_processed_/1/0/csm_EUAIAct_Headerbild_510724b3de.webp)

    ###  AI Content in TYPO3: Labelling Needs Accountability

     02 August 2026 | Benni Mack

     The EU AI Act brings the origins of AI-generated content into focus. AI Label marks AI-generated and AI-edited content in TYPO3 and records who signed off the published version—for…

     [ Read more: AI Content in TYPO3: Labelling Needs Accountability ](https://b13.com/knowledge/ai-content-in-typo3-labelling-needs-accountability)
- ![A cartoon character resembling a shield gives a thumbs up in front of a computer interface with various menu options.](https://b13.com/fileadmin/_processed_/e/6/csm_Header_cda1f80173.webp)

    ###  Meet T3ppy: A New Era for Editorial Work in TYPO3

     01 April 2026 | Florian “Flix” Keitgen

     T3ppy and the AiM extension bring AI directly into the TYPO3 backend—enhancing SEO, content quality, and workflows with centralized control.

     [ Read more: Meet T3ppy: A New Era for Editorial Work in TYPO3 ](https://b13.com/knowledge/meet-t3ppy-a-new-era-for-editorial-work-in-typo3)
- ![Retro microphone illustration with a shopping cart icon in the background, symbolizing e-commerce or online shopping.](https://b13.com/fileadmin/_processed_/f/8/csm_Marketplace_Headerbild_ee1575614c.webp)

    ###  Why TYPO3 Needs a Marketplace for Products

     25 March 2026 | Florian “Flix” Keitgen

     A marketplace would make TYPO3 products more discoverable, easier to compare, and benefit both agencies and clients alike.

     [ Read more: Why TYPO3 Needs a Marketplace for Products ](https://b13.com/knowledge/why-typo3-needs-a-marketplace-for-products)
- ![A hand holding a magnifying glass over a laptop screen displaying a webpage with an image and text elements.](https://b13.com/fileadmin/_processed_/e/5/csm_BackendUserSection_Headerbild_6093c842fd.webp)

    ###  Unlocking TYPO3’s Hidden Gem: The Backend User Section (Doktype 6)

     05 March 2026 | David Steeb

     Discover TYPO3’s underrated doktype 6 (Backend User Section) for secure internal previews, editor training, and prototyping. Learn real use cases, common pitfalls like 403 errors…

     [ Read more: Unlocking TYPO3’s Hidden Gem: The Backend User Section (Doktype 6) ](https://b13.com/knowledge/backend-user-section-in-typo3-uses-pitfalls-helper)
- ![Two stylized web page designs featuring a user profile, image placeholders, and text sections, set against a light blue background.](https://b13.com/fileadmin/_processed_/2/0/csm_BackendPreview_Headerbild_b4c5799cfa.webp)

    ###  Backend Previews With a System—Why We Built EXT:backendpreviews

     09 February 2026 | David Steeb

     EXT:backendpreviews brings structure and consistency to content previews in the TYPO3 backend using Fluid templates, layouts, and partials.

     [ Read more: Backend Previews With a System—Why We Built EXT:backendpreviews ](https://b13.com/knowledge/backend-previews-with-a-system-why-we-built-extbackendpreviews)
- ![A human hand shakes a robotic hand against a purple background with heart patterns, symbolizing collaboration between humans and technology.](https://b13.com/fileadmin/_processed_/6/2/csm_AIbotsLoveMarkdown_Headerbild_72fe5820d6.webp)

    ###  The Internet Is No Longer Just for Humans—AI Bots Love Markdown

     28 January 2026 | Benni Mack

     Discover why most web traffic is now automated and how TYPO3’s structured content model prepares websites for humans, editors, and AI systems.

     [ Read more: The Internet Is No Longer Just for Humans—AI Bots Love Markdown ](https://b13.com/knowledge/the-internet-is-no-longer-just-for-humans-ai-bots-love-markdown)
- ![Several colorful web page mockups stacked together, showcasing different layouts and design elements against a purple background.](https://b13.com/fileadmin/_processed_/e/3/csm_CaminoTheme_Headerbild_d082598009.webp)

    ###  Camino—The Need for a Default Theme in TYPO3 Is Real

     27 January 2026 | Benni Mack

     With TYPO3 v14, Camino introduces a default theme that removes friction from first installs. Why this matters—and how TYPO3 laid the groundwork.

     [ Read more: Camino—The Need for a Default Theme in TYPO3 Is Real ](https://b13.com/core-insights/blog/camino-the-need-for-a-default-theme-in-typo3-is-real)
- ![Graphic featuring stylized representations of a tower with the text "T3CON25 Düsseldorf" prominently displayed in the center.](https://b13.com/fileadmin/_processed_/7/b/csm_T3CON2025_Headerbild_fc9c5cc53e.webp)

    ###  T3CON25—One Step Closer to the Future of Content Management

     10 December 2025 | Franzi Töpler

     T3CON25 showcased the future of TYPO3 with insights on TYPO3 v14, AI, digital sovereignty, and open-source solutions driving secure, modern web experiences.

     [ Read more: T3CON25—One Step Closer to the Future of Content Management ](https://b13.com/knowledge/shaping-the-future-of-content-management-t3con25)
- ![Colorful sneakers are repeated in a pattern, with a central logo featuring "TYPO3 Code Sprint."](https://b13.com/fileadmin/_processed_/6/c/csm_CodesprintGenf25_Headerbild_c44149748c.webp)

    ###  Coding, Collaboration, and Community: My Week at the TYPO3 v14 Feature Sprint in Geneva

     05 November 2025 | Oliver Bartsch

     Five days, 14 contributors, countless ideas—and 55 patches created! Our team at b13 joined the TYPO3 v14 Feature Sprint in Geneva to push key improvements for backend UX, APIs, and…

     [ Read more: Coding, Collaboration, and Community: My Week at the TYPO3 v14 Feature Sprint in Geneva ](https://b13.com/knowledge/coding-collaboration-and-community-my-week-at-the-typo3-v14-feature-sprint-in-geneva)