Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Messenger Mongo Bundle Laravel Package

emag-tech-labs/messenger-mongo-bundle

A Symfony Messenger transport that stores queued and failed messages in MongoDB. Install via Composer, configure DSN, database, collection, queue, and redeliver timeout, then use standard Messenger retry and failed-message commands.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the bundle and make sure the MongoDB extension and library are present:

composer require emag-tech-labs/messenger-mongo-bundle
php -m | grep mongodb        # ext-mongodb must be loaded

Check config/bundles.php; if Flex did not register it, add:

EmagTechLabs\MessengerMongoBundle\MessengerMongoBundle::class => ['all' => true],

The first thing to look at is the transport factory and transport classes inside the bundle (Transport/ directory) — that is where the DSN scheme, supported options, and the collection document shape are defined. Then wire a transport:

# config/packages/messenger.yaml
framework:
    messenger:
        transports:
            mongo_async:
                dsn: '%env(MESSENGER_MONGO_DSN)%'
                options:
                    database: 'app'
                    collection: 'messenger_messages'
# .env
MESSENGER_MONGO_DSN=mongodb://mongo:27017

Route a message and consume it:

framework:
    messenger:
        routing:
            'App\Message\SendWelcomeEmail': mongo_async
$this->bus->dispatch(new SendWelcomeEmail($userId));
bin/console messenger:consume mongo_async -vv

First use case to adopt: make it the failure_transport before using it for primary async work. The bundle's sweet spot is persistent failed-message storage in an app that already runs MongoDB:

framework:
    messenger:
        failure_transport: mongo_failed
        transports:
            mongo_failed:
                dsn: '%env(MESSENGER_MONGO_DSN)%'
                options:
                    database: 'app'
                    collection: 'messenger_failed'

Then use messenger:failed:show, messenger:failed:retry, and messenger:failed:remove exactly as with Doctrine or AMQP.

Implementation Patterns

Separate collections per transport. Treat one Mongo collection as one queue. It keeps inspection, indexing, and truncation simple, and avoids relying on filtering fields inside a shared collection:

transports:
    mongo_async:
        dsn: '%env(MESSENGER_MONGO_DSN)%'
        options: { database: 'app', collection: 'messenger_async' }
    mongo_failed:
        dsn: '%env(MESSENGER_MONGO_DSN)%'
        options: { database: 'app', collection: 'messenger_failed' }

Use it for low-to-moderate volume async, not bulk pipelines. It behaves like a polling queue rather than a push broker. Good fits: emails, webhooks, report generation, cache warmups, exports. Poor fits: thousands of messages per second, strict FIFO, or latency-sensitive jobs.

Configure retries on the transport, not only in handlers:

mongo_async:
    dsn: '%env(MESSENGER_MONGO_DSN)%'
    retry_strategy:
        max_retries: 3
        delay: 1000
        multiplier: 2
        max_delay: 10000

Design handlers for at-least-once delivery. A consumer crash, timeout, or visibility expiry can cause redelivery. Use idempotency keys, unique constraints, or “already processed” markers:

public function __invoke(SendWelcomeEmail $message): void
{
    if ($this->processedLog->exists($message->id)) {
        return;
    }
    // ...
    $this->processedLog->mark($message->id);
}

Pass a dedicated MongoDB client for auth, TLS, or replica-set DSNs. If the factory accepts a client option/service, reference a configured MongoDB\Client service rather than embedding credentials and query parameters in the Messenger DSN:

services:
    app.mongo_client:
        class: MongoDB\Client
        arguments: ['%env(MONGODB_URI)%']

transports:
    mongo_async:
        dsn: '%env(MESSENGER_MONGO_DSN)%'
        options:
            database: 'app'
            collection: 'messenger_async'
            client: 'app.mongo_client'

Confirm the exact option name in the bundle factory; this is the main integration point to verify against the installed version.

Worker operations. Run consumers under Supervisor or systemd with bounded lifetimes so PHP memory is recycled:

bin/console messenger:consume mongo_async mongo_failed \
    --time-limit=3600 \
    --memory-limit=128M \
    --sleep=1 \
    -vv

Use bin/console messenger:stop-workers as part of deployment so old workers exit cleanly after a code deploy.

Give the application a restricted Mongo user that has readWrite only on the messenger collections, plus createCollection if the bundle auto-creates them. If production users cannot create collections, pre-create them via migration/provisioning and set any auto-setup option off.

Monitor as a collection, not as a queue. Useful day-to-day queries:

// backlog
db.messenger_async.countDocuments({})

// oldest waiting item — confirm the actual field names in the transport source
db.messenger_async.find().sort({created_at: 1}).limit(1)

// failure inspection
db.messenger_failed.find().sort({created_at: -1}).limit(5)

Gotchas and Tips

  • MongoDB is not a queue broker. There is no blocking pop or push notification; consumers poll. Tune --sleep and worker count deliberately. Empty polling loops are cheap but not free.
  • BSON document limit is 16 MB. Serialized envelopes containing large arrays, base64 files, or full entities can exceed it. Store large payloads in GridFS or object storage and dispatch only an identifier.
  • Pay attention to indexes. The transport queries on availability/creation/queue fields. Without indexes, consumption slows as the collection grows. Inspect the bundle's setup code or create indexes manually on the fields it filters and sorts by.
  • Visibility/redelivery timeouts cause duplicates. Long-running handlers can exceed the transport's redelivery window and be picked up again. Keep handlers short, or raise the relevant option if exposed, and make processing idempotent.
  • Standalone MongoDB vs replica set. If the transport or your own code relies on transactions, a standalone mongod will not support them. Verify the bundle's claim strategy and use a replica set in production if needed.
  • Do not TTL-index active queues. A TTL index on created_at will delete waiting messages. If you want retention on the failure collection, apply TTL only there and only after deciding how long failures must remain retryable.
  • Serialization is a deployment contract. Renaming, moving, or deleting message classes breaks documents already in the collection. Keep class names stable, deploy producers/consumers carefully, or configure a serializer with class aliases.
  • Credentials in DSNs need URL encoding. Special characters in usernames/passwords will break URI parsing. Prefer a separately configured MongoDB\Client service for complex auth.
  • Failure transport loops. If mongo_failed is also routed into the same failing workflow, messenger:failed:retry can bounce messages straight back. Keep failure transport isolated from normal routing.
  • Debugging: start with messenger:consume -vvv, then inspect the raw documents in the collection. Check _id, timestamps, and whether the message was acknowledged/removed. Enable MongoDB driver logging in dev if the transport swallows connection issues.
  • Extension points: decorate the bundle's transport/factory services to add logging, metrics, or custom claim behavior, and prefer Symfony's serializer configuration over modifying the vendor code. Keep an eye on the bundle's releases — at 16 stars and low dependent count, pin a version and read the changelog before upgrading.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums