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

Nats Php Bundle Laravel Package

elandlord/nats-php-bundle

A Symfony bundle that integrates NATS with Symfony Messenger using a NatsConnection, helping you publish and consume messages through NATS in Symfony applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Know what the bundle does and doesn't do. Despite the name, this is not a NATS client. It is a thin Symfony Messenger transport that reuses an existing NatsConnection service and hands publish/consume to Messenger's bus, routing, retry, and middleware stack. First mental model: you own the connection and the broker topology; the bundle owns the transport glue.

Minimal setup:

  1. A reachable NATS server (JetStream enabled if you want persistence, durables, or replay — core NATS is fire-and-forget).
  2. A NatsConnection service in your container, from the companion elandlord/nats-php package. This is the step people miss: if no NatsConnection is registered/aliased, the transport can't be built. Wire it explicitly in config/services.yaml rather than hoping for autowiring.
  3. Install the bundle (composer require elandlord/nats-php-bundle) and let Flex register it, or add it to config/bundles.php.
  4. Point a Messenger transport at it and route one message class to that transport.
# config/packages/messenger.yaml
framework:
    messenger:
        transports:
            nats_events:
                dsn: '%env(MESSENGER_NATS_DSN)%'
        routing:
            App\Message\UserCreated: nats_events

The exact DSN scheme and available transport options are whatever NatsTransportFactory::supports() and the bundle's Configuration.php accept — there is no meaningful config reference in the README, so read those two files first, then confirm with bin/console config:dump-reference / debug:config.

Where to look first, in order:

  • DependencyInjection/Configuration.php — the real documentation.
  • Transport/NatsTransportFactory.php and Transport/NatsTransport.php — DSN parsing, subject/stream/consumer option names, ack behaviour.
  • Resources/config/services.* — which service ids/aliases exist and what the transport is injected with.

First day-one use case: take one non-critical, fire-and-forget event (analytics ping, notification, audit log), dispatch it from a controller via MessageBusInterface, and run bin/console messenger:consume nats_events -vv in a terminal. Watch the message land, the handler fire, and the ack settle. That single loop exercises routing, serialization, and acking — the three things that break in production.

Implementation Patterns

Message DTO + handler, routed by class. Stay inside Messenger conventions instead of touching the transport directly:

final class UserCreated
{
    public function __construct(
        public readonly string $userId,
        public readonly \DateTimeImmutable $occurredAt,
    ) {}
}

Dispatch with $bus->dispatch(new UserCreated($id, new \DateTimeImmutable())) and let framework.messenger.routing decide the transport. This keeps NATS swappable — moving to AMQP later is a config change, not a refactor.

Serialization is Symfony Serializer, not raw JSON. Since v1.3.0 the bundle hydrates messages through the Symfony Serializer, and v1.4.1 added BackedEnumNormalizer. In practice: type your constructor properties (including backed enums and DateTimeImmutable), keep message classes immutable, and make sure the normalizer set you need is enabled on the serializer the bundle picks up. Avoid untyped array $payload constructors — you lose the benefit and inherit all the fragility.

Durable consumer config as code. With v1.4.3, consumer configuration changes are applied to existing durable consumers instead of being silently ignored. Treat the transport's consumer block in messenger.yaml as production configuration: review diffs, and evolve filter subjects/durables deliberately rather than assuming a config edit is inert.

Middleware is where the operational behaviour lives. Because this is a Messenger transport, you get for free:

  • doctrine_transaction around handlers that write to the DB,
  • failed transport for poison messages (messenger:failed:show / :retry),
  • custom middleware for correlation IDs, structured logging, or tracing.

Add a logging middleware before you need it — NATS failures are otherwise quiet.

Worker supervision. Long-lived messenger:consume processes should run under Supervisor/systemd with --time-limit and --memory-limit so connections are periodically recycled, and messenger:stop-workers should be part of your deploy so code changes take effect.

Multiple transports for isolation. One transport per stream/subject family (e.g. nats_events, nats_jobs) maps cleanly onto separate worker pools with different concurrency and retry policies, and keeps a noisy consumer from starving a critical one.

Extension points worth knowing: a custom SerializerInterface if you need Protobuf/Avro, a decorating service around NatsConnection for metrics and connection health, and custom Messenger middleware for cross-cutting policy.

Gotchas and Tips

  • The bundle does not create the connection. No NatsConnection service ⇒ transport construction fails, usually with a DI error that doesn't mention NATS at all. If autowiring fails, define the service explicitly and check the alias the transport factory expects.
  • Pin to >=1.4.0 for ack correctness. v1.4.0 is literally "fix to ack nats message." On earlier versions you can expect redelivery storms under load. Similarly, v1.2.0 fixed consumer unsubscribe and performance, and v1.1.0 fixed messages simply not being picked up — this library's history is a list of "silently does nothing" bugs, so pin deliberately and read the changelog before upgrading.
  • Silent no-consume is the signature failure. Wrong subject, wrong filter subject, wrong stream, or a durable whose config doesn't match expectations all manifest as no errors, no messages. Debug from the broker side first: nats consumer info <stream> <durable> and nats stream view tell you whether anything arrived and whether the consumer is bound. Then check debug:messenger on the PHP side.
  • v1.4.3 removed a safety rail. Consumer config now mutates existing durables on the next worker start. Capture nats consumer info output before deploys, and know that some durable fields are immutable — attempting to change them fails or leaves broker state diverged from your YAML. Keep a delete-and-recreate runbook.
  • Core NATS ≠ JetStream. Without JetStream you have at-most-once delivery and no replay; retries and failed transports won't save a message that was never persisted. Decide which guarantee you're buying before you promise anyone "it's queued."
  • Serializer failures look like handler failures. If the payload shape doesn't match the constructor, the message fails during hydration; check messenger:failed:show -vv before blaming your handler.
  • DSN/env quirks. NATS URLs with credentials and multiple servers involve characters that play badly with env var processing. Quote the env value, and verify what the transport actually parsed rather than what you think you set — a comma list or a stray colon can silently select the wrong server or drop auth.
  • Docs are one sentence; four stars and zero dependents. Budget for source reading, and isolate the transport behind your own message classes and routing config so a swap (or an unmaintained package) is a config change. Subscribe to releases — the changelog is the documentation, and it's unusually load-bearing here.
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.
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin