The Principal Dev – Masterclass for Tech Leads

The Principal Dev – Masterclass for Tech Leads28-29 May

Join

This is Read Only Repository

To contribute make use of Ecotone-Dev repository.

Github Actions Latest Stable Version License Total Downloads PHP Version Require

Ecotone — the PHP architecture layer that grows with your system, without rewrites

From #[CommandHandler] on day one, to event sourcing, sagas, outbox, and distributed messaging at scale — one package, same codebase, no forced migrations between growth stages. Declarative PHP 8 attributes on the classes you already have. No base classes, no bus wiring, no retry config.

Built on Enterprise Integration Patterns — the same pattern language behind Spring Integration, Axon, NServiceBus, and Apache Camel — brought to PHP as attribute-driven code.

Visit ecotone.tech for the full overview.


See what it looks like

class OrderService
{
    #[CommandHandler]
    public function placeOrder(PlaceOrder $command, EventBus $eventBus): void
    {
        // your business logic
        $eventBus->publish(new OrderWasPlaced($command->orderId));
    }

    #[QueryHandler('order.getStatus')]
    public function getStatus(string $orderId): string
    {
        return $this->orders[$orderId]->status;
    }
}

class NotificationService
{
    #[Asynchronous('notifications')]
    #[EventHandler]
    public function whenOrderPlaced(OrderWasPlaced $event, NotificationSender $sender): void
    {
        $sender->sendOrderConfirmation($event->orderId);
    }
}

That's the entire setup. No bus configuration. No handler registration. No retry config. No serialization wiring. Ecotone reads your attributes and handles the rest:


Test exactly the flow you care about

Extract a specific flow and test it in isolation — only the services you need:

$ecotone = EcotoneLite::bootstrapFlowTesting([OrderService::class]);

$ecotone->sendCommand(new PlaceOrder('order-1'));

$this->assertEquals('placed', $ecotone->sendQueryWithRouting('order.getStatus', 'order-1'));

Only OrderService is loaded — no notifications, no other handlers. Just the flow you're verifying.

Now bring in the full async flow. Enable an in-memory channel and run it inside the same test process:

$notifier = new InMemoryNotificationSender();

$ecotone = EcotoneLite::bootstrapFlowTesting(
    [OrderService::class, NotificationService::class],
    [NotificationSender::class => $notifier],
    enableAsynchronousProcessing: [
        SimpleMessageChannelBuilder::createQueueChannel('notifications')
    ]
);

$ecotone
    ->sendCommand(new PlaceOrder('order-1'))
    ->run('notifications');

$this->assertEquals(['order-1'], $notifier->getSentOrderConfirmations());

Swap the in-memory channel for DBAL, RabbitMQ, or Kafka in production — the test stays the same. Ecotone runs the consumer in-process, so switching transports never changes how you test.


What's in the box

Area What you get
Messaging Command / Query / Event buses, routing, interceptors, business interfaces (gateways)
Domain modelling Aggregates, Sagas, state-stored or event-sourced — all via attributes
Event Sourcing Event Store, Projections (catch-up, partitioned, streaming), event versioning and upcasting, DCB
Workflows Stateless workflows, orchestrators (routing slip), saga-based process managers
Async & resiliency #[Asynchronous], retries, error channels, dead letter queue with replay, Outbox pattern
Observability OpenTelemetry tracing, Service Map (Enterprise)
Multi-tenancy Per-tenant connections, event stores, and async channels
Distribution Distributed Bus for cross-service events and commands
Data protection Field-level encryption and PII masking for messages

Install for your framework

Ecotone is not a replacement for Symfony Messenger or Laravel Queue — it's the architecture layer on top. Your existing HTTP layer, transports, and jobs keep working.

Symfony

composer require ecotone/symfony-bundle

Symfony Messenger compatible. Bundle auto-configuration. Doctrine ORM integration. Pure POPOs. → Symfony guide

Laravel

composer require ecotone/laravel

Works with Eloquent and Doctrine. Laravel Queue integration. Auto-discovery, zero config. → Laravel guide

Any PSR-11 framework (Ecotone Lite)

composer require ecotone/ecotone

Full feature set. No framework lock-in. → Ecotone Lite guide


AI-Ready by design

Declarative attributes mean less infrastructure code for your coding agent to read and less boilerplate for it to generate — smaller context, faster iteration, more accurate results.

Learn more: AI Integration Guide


Getting started

See the quickstart guide, the full documentation, and the Ecotone Blog.

Prefer runnable code? The quickstart examples cover handlers, aggregates, sagas, event sourcing, projections, outbox, multi-tenancy, and more — each running end-to-end in seconds.

Feature requests and issue reporting

Use issue tracking system for new feature request and bugs. Please verify that it's not already reported by someone else.

Contact

If you want to talk or ask questions about Ecotone

Support Ecotone

If you want to help building and improving Ecotone consider becoming a sponsor:

Tags

PHP, DDD, CQRS, Event Sourcing, Sagas, Projections, Workflows, Outbox, Symfony, Laravel, Service Bus, Event Driven Architecture

Join libs.tech

...and unlock some superpowers

GitHub

We won't share your data with anyone else.