# About

<figure><img src="https://1452285857-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LmAUnBnyZgZuLF2eWLn%2Fuploads%2Fgit-blob-82b4ea59bc3340bbe1eeda4b3dd49bb1b7fdcf5d%2Fecotone_logo_no_background.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

## Ecotone extends your existing Laravel and Symfony application with the enterprise architecture layer

One Composer package adds CQRS, Event Sourcing, Workflows, and production resilience to your codebase. No framework change. No base classes. Just PHP attributes on your existing code.

```bash
composer require ecotone/laravel    # or ecotone/symfony-bundle
```

***

## See what it looks like

```php
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:

* **Command and Query Bus** — wired automatically from your `#[CommandHandler]` and `#[QueryHandler]` attributes
* **Event routing** — `NotificationService` subscribes to `OrderWasPlaced` without any manual wiring
* **Async execution** — `#[Asynchronous('notifications')]` routes to RabbitMQ, SQS, Kafka, or DBAL — your choice of transport
* **Failure isolation** — each event handler gets its own copy of the message, so one handler's failure never blocks another
* **Retries and dead letter** — failed messages retry automatically, permanently failed ones go to a [dead letter queue](https://docs.ecotone.tech/modelling/recovering-tracing-and-monitoring/resiliency/error-channel-and-dead-letter) you can inspect and replay
* **Tracing** — [OpenTelemetry integration](https://docs.ecotone.tech/modelling/recovering-tracing-and-monitoring) traces every message across sync and async flows

### Test exactly the flow you care about

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

```php
$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 within the same test process:

```php
$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());
```

`->run('notifications')` processes messages from the in-memory queue — right in the same process. The async handler executes deterministically, no timing issues, no polling, no external broker.

**The key:** swap the in-memory channel for [DBAL](https://github.com/ecotoneframework/documentation/blob/main/modules/dbal-support/README.md), [RabbitMQ](https://docs.ecotone.tech/modules/amqp-support-rabbitmq), or [Kafka](https://docs.ecotone.tech/modules/kafka-support) to test what runs in production — the test stays the same. Ecotone runs the consumer within the same process, so switching transports never changes how you test. The ease of in-memory testing [stays with you](https://docs.ecotone.tech/modelling/testing-support) no matter what backs your production system.

***

## What changes in your daily work

### Business logic is the only code you write

No command bus configuration. No handler registration. No message serialization setup. You write a PHP class with an attribute, and Ecotone wires the bus, the routing, the serialization, and the async transport. Your code stays focused on what your application actually does — your domain.

### Going async never means rewriting handlers

Add `#[Asynchronous('channel')]` to any handler. The handler code stays identical. Switch from synchronous to [RabbitMQ](https://docs.ecotone.tech/modules/amqp-support-rabbitmq) to [SQS](https://github.com/ecotoneframework/documentation/blob/main/modules/sqs-support/README.md) to [Kafka](https://docs.ecotone.tech/modules/kafka-support) by changing one line of configuration. Your business logic never knows the difference.

### Failed messages don't disappear

Every failed message is captured in a [dead letter queue](https://docs.ecotone.tech/modelling/recovering-tracing-and-monitoring/resiliency/error-channel-and-dead-letter). You see what failed, the full exception, and the original message. [Replay it](https://docs.ecotone.tech/modelling/recovering-tracing-and-monitoring/resiliency/error-channel-and-dead-letter/dbal-dead-letter) with one command. And can be combined with inbuilt Outbox pattern to ensure full consistency. No more silent failures. No more guessing what happened to that order at 3am.

### Complex workflows live in one place

A multi-step business process — order placement, payment, shipping, notification — doesn't need to be scattered across event listeners, cron jobs, and database flags. Ecotone gives you [Sagas](https://docs.ecotone.tech/modelling/business-workflows/sagas) for stateful workflows, [handler chaining](https://docs.ecotone.tech/modelling/business-workflows/connecting-handlers-with-channels) for linear pipelines, and [Orchestrators](https://docs.ecotone.tech/modelling/business-workflows/orchestrators) for declarative process control. The entire business flow is readable in one class.

### Your codebase tells the story of your business

When a new developer opens your code, they see `PlaceOrder`, `OrderWasPlaced`, `ShipOrder` — not `AbstractMessageBusHandlerFactory`. Ecotone keeps your domain clean: no base classes to extend, no framework interfaces to implement, no infrastructure leaking into your business logic. Just [plain PHP objects](https://docs.ecotone.tech/modelling/command-handling) with attributes that declare their intent.

***

## The full capability set

| Capability                | What it gives you                                                                                     | Learn more                                                                                       |
| ------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| **CQRS**                  | Separate command and query handlers. Clean responsibility boundaries. Automatic bus wiring.           | [Command Handling](https://docs.ecotone.tech/modelling/command-handling)                         |
| **Event Sourcing**        | Store events instead of state. Full audit trail. Rebuild read models anytime. Time travel and replay. | [Event Sourcing](https://docs.ecotone.tech/modelling/event-sourcing)                             |
| **Workflows & Sagas**     | Orchestrate multi-step business processes. Stateful workflows with compensation logic.                | [Business Workflows](https://docs.ecotone.tech/modelling/business-workflows)                     |
| **Async Messaging**       | RabbitMQ, Kafka, SQS, Redis, DBAL. One attribute to go async. Swap transports without code changes.   | [Asynchronous Handling](https://docs.ecotone.tech/modelling/asynchronous-handling)               |
| **Production Resilience** | Automatic retries, dead letter queues, outbox pattern, message deduplication, failure isolation.      | [Resiliency](https://docs.ecotone.tech/modelling/recovering-tracing-and-monitoring/resiliency)   |
| **Domain-Driven Design**  | Aggregates, domain events, bounded contexts. Pure PHP objects with no framework coupling.             | [Aggregates](https://docs.ecotone.tech/modelling/command-handling/state-stored-aggregate)        |
| **Distributed Bus**       | Cross-service messaging. Share events and commands between microservices with guaranteed delivery.    | [Microservices](https://docs.ecotone.tech/modelling/microservices-php)                           |
| **Multi-Tenancy**         | Tenant-isolated processing, projections, and event streams. Built in, not bolted on.                  | [Multi-Tenancy](https://docs.ecotone.tech/messaging/multi-tenancy-support)                       |
| **Observability**         | OpenTelemetry integration. Trace every message — sync or async — across your entire system.           | [Monitoring](https://docs.ecotone.tech/modelling/recovering-tracing-and-monitoring)              |
| **Interceptors**          | Cross-cutting concerns — authorization, logging, transactions — applied declaratively via attributes. | [Interceptors](https://docs.ecotone.tech/modelling/extending-messaging-middlewares/interceptors) |

***

## The enterprise gap in PHP, closed

Every mature ecosystem has an enterprise architecture layer on top of its web framework:

| Ecosystem | Web Framework     | Enterprise Architecture Layer       |
| --------- | ----------------- | ----------------------------------- |
| **Java**  | Spring Boot       | Spring Integration + Axon Framework |
| **.NET**  | ASP.NET           | NServiceBus / MassTransit           |
| **PHP**   | Laravel / Symfony | **Ecotone**                         |

Ecotone is built on the same foundation — [Enterprise Integration Patterns](https://www.enterpriseintegrationpatterns.com/) — that powers Spring Integration, NServiceBus, and Apache Camel. In active development since 2017 and used in production by teams running multi-tenant, event-sourced systems at scale, Ecotone brings the same patterns that run banking, logistics, and telecom systems in Java and .NET to PHP.

This isn't about PHP catching up. It's about your team using proven architecture patterns — with the development speed that PHP gives you — without giving up the ecosystem you already know.

[Read more: Why Ecotone?](https://docs.ecotone.tech/why-ecotone)

***

## Start with your framework

**Laravel** — Keep Eloquent, Laravel Queues, and Octane. Add what Laravel doesn't have: Event Sourcing, Sagas, failure isolation per handler, synchronous testing of async flows, and outbox pattern.\
`composer require ecotone/laravel`\
→ [Laravel Quick Start](https://docs.ecotone.tech/quick-start-php-ddd-cqrs-event-sourcing/laravel-ddd-cqrs-demo-application) · [Laravel Module docs](https://docs.ecotone.tech/modules/laravel)

**Symfony** — Symfony Messenger gives you a message bus. Ecotone gives you the complete architecture: Event Sourcing with projections, Sagas for stateful workflows, per-handler failure isolation, dead letter queue with replay, and synchronous testing of async flows.\
`composer require ecotone/symfony-bundle`\
→ [Symfony Quick Start](https://docs.ecotone.tech/quick-start-php-ddd-cqrs-event-sourcing/symfony-ddd-cqrs-demo-application) · [Symfony Module docs](https://docs.ecotone.tech/modules/symfony)

**Any PHP framework** — Ecotone Lite works with any PSR-11 compatible container.\
`composer require ecotone/lite-application`\
→ [Ecotone Lite docs](https://docs.ecotone.tech/modules/ecotone-lite)

***

**Try it in one handler.** You don't need to migrate your application. Install Ecotone, add an attribute to one handler, and see what happens. If you like what you see, add more. If you don't — remove the package. Zero commitment.

* [Install](https://docs.ecotone.tech/install-php-service-bus) — Setup guide for any framework
* [Learn by example](https://docs.ecotone.tech/quick-start-php-ddd-cqrs-event-sourcing) — Send your first command in 5 minutes
* [Go through tutorial](https://docs.ecotone.tech/tutorial-php-ddd-cqrs-event-sourcing) — Build a complete messaging flow step by step
* [Workshops, Support, Consultancy](https://docs.ecotone.tech/other/contact-workshops-and-support) — Hands-on training for your team

{% hint style="info" %}
The full CQRS, Event Sourcing, and Workflow feature set is [free and open source](https://docs.ecotone.tech/enterprise) under the Apache 2.0 License. [Enterprise features](https://docs.ecotone.tech/enterprise) are available for teams that need advanced scaling, distributed bus with service map, orchestrators, and production-grade Kafka integration.
{% endhint %}

{% hint style="success" %}
Join [Ecotone's Community Channel](https://discord.gg/GwM2BSuXeg) — ask questions and share what you're building.
{% endhint %}
