PHPackages                             wwwision/dcb-example - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. wwwision/dcb-example

ActiveProject

wwwision/dcb-example
====================

Simple example for the Dynamic Consistency Boundary pattern described by Sara Pellegrini

2.0.1(1y ago)2051[6 PRs](https://github.com/bwaidelich/dcb-example-courses/pulls)MITPHPPHP &gt;=8.4

Since Jun 5Pushed 2mo ago2 watchersCompare

[ Source](https://github.com/bwaidelich/dcb-example-courses)[ Packagist](https://packagist.org/packages/wwwision/dcb-example)[ GitHub Sponsors](https://github.com/sponsors/bwaidelich)[ Fund](https://www.paypal.me/bwaidelich)[ RSS](/packages/wwwision-dcb-example/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (8)Dependencies (8)Versions (14)Used By (0)

Dynamic Consistency Boundary Example
====================================

[](#dynamic-consistency-boundary-example)

Simple example for the Dynamic Consistency Boundary pattern [described by Sara Pellegrini](https://sara.event-thinking.io/2023/04/kill-aggregate-chapter-1-I-am-here-to-kill-the-aggregate.html).

The purpose of this package is to explore the idea, find potential pitfalls and to spread the word.

**tl;dr** Have a look at the [example script](index.php) or [Behat Tests](tests/Behat) to see this in action.

Background
----------

[](#background)

Dynamic Consistency Boundary (aka DCB) allow to enforce hard constraints in Event-Sourced systems without having to rely on individual Event Streams. This facilitates focussing on the *behavior* of the Domain Model rather than on its rigid structure. It also allows for simpler architecture and potential performance improvements as multiple projections can act on the same events without requiring synchronization.

Read all about this interesting approach in the blog post mentioned above or watch Saras talk on [YouTube](https://www.youtube.com/watch?v=DhhxKoOpJe0&t=150s) (Italian with English subtitles). This package models the example of this presentation (with a few deviations) using the [wwwision/dcb-eventstore](https://github.com/bwaidelich/dcb-eventstore) package and the [wwwision/dcb-eventstore-doctrine](https://github.com/bwaidelich/dcb-eventstore-doctrine) database adapter.

### Important Classes / Concepts

[](#important-classes--concepts)

- [Commands](src%2FCommand) are just a concept of this example package. They implement the [Command Marker Interface](src%2FCommand%2FCommand.php)
- The [CommandHandler](src/CommandHandler.php) is the central authority, handling and verifying incoming Command
- It uses in-memory [Projections](src%2FProjection%2FProjection.php) to enforce hard constraints
- For each command handler a [DecisionModel](src%2FDecisionModel%2FDecisionModel.php) instance is built that contains the state of those in-memory projections and the [AppendCondition](https://github.com/bwaidelich/dcb-eventstore/blob/main/Specification.md#AppendCondition) for new events
- The [EventSerializer](src%2FEventSerializer.php) can convert [DomainEvent](src%2FEvent%2DDomainEvent.php) instances to writable events, vice versa
- *Note:* This package contains no Read Model (i.e. classic projections) yet

### Considerations / Findings

[](#considerations--findings)

I always had the feeling, that the focus on Event Streams is a distraction to Domain-driven design. So I was very happy to come across this concept. In the meantime I have had the chance to test it in multiple real world scenarios, and it works really well for me and simplifies things (in spite of some minor caveats in the current implementation):

- It becomes trivial to enforce constraints involving multiple entities (like in this example).
- Global uniqueness (aka "the unique username problem") can easily be achieved with DCB
- Consecutive sequences (e.g. invoice number) can be done without reservation patterns and by only reading a single event per constraint check
- When using composition like in this example, phe in-memory projections are surprisingly small because they focus on a single responsibility
- ...and more

Usage
-----

[](#usage)

Install via [composer](https://getcomposer.org):

```
composer create-project wwwision/dcb-example-courses
```

Now you should be able to run the [example script](index.php) via

```
php dcb-example-courses/index.php
```

And you should get ...no output at all. That's because the example script currently satisfy all constraints. Try changing the script to test, that the business rules are actually enforced, for example you could add the line:

```
$commandHandler->handle(SubscribeStudentToCourse::create(courseId: 'c1', studentId: 's2'));
```

to the end of the file, which should lead to the following exception:

```
Failed to subscribe student with id "s2" to course with id "c1" because a student with that id does not exist

```

Alternatively, you could have a look at the [Behat Tests](tests/Behat):

Tests
-----

[](#tests)

This package comes with 16 Behat scenarios covering all business features. You can run the tests via

```
composer test:behat
```

Acknowledgment
--------------

[](#acknowledgment)

Most of the implementation of these packages are based on the great groundwork done by [Sara Pellegrini](https://sara.event-thinking.io/), so all praise belong to her!

Contributions
-------------

[](#contributions)

I'm really curious to get feedback on this one. Feel free to start/join a [discussion](https://github.com/bwaidelich/dcb-example/discussions), [issues](https://github.com/bwaidelich/dcb-example/issues) or [Pull requests](https://github.com/bwaidelich/dcb-example/pulls).

###  Health Score

42

—

FairBetter than 90% of packages

Maintenance64

Regular maintenance activity

Popularity13

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity69

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~69 days

Recently: every ~138 days

Total

9

Last Release

523d ago

Major Versions

1.0.x-dev → 2.0.02024-12-10

PHP version history (3 changes)1.0.0PHP 8.2

1.2.1PHP &gt;=8.2

2.0.0PHP &gt;=8.4

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/307571?v=4)[Bastian Waidelich](/maintainers/bwaidelich)[@bwaidelich](https://github.com/bwaidelich)

---

Top Contributors

[![bwaidelich](https://avatars.githubusercontent.com/u/307571?v=4)](https://github.com/bwaidelich "bwaidelich (29 commits)")

---

Tags

dcbddddomaindrivendesigndynamicconsistencyboundaryeventsourcing

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/wwwision-dcb-example/health.svg)

```
[![Health](https://phpackages.com/badges/wwwision-dcb-example/health.svg)](https://phpackages.com/packages/wwwision-dcb-example)
```

###  Alternatives

[phpdocumentor/reflection-docblock

With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.

9.4k722.2M1.2k](/packages/phpdocumentor-reflection-docblock)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[infection/infection

Infection is a Mutation Testing framework for PHP. The mutation adequacy score can be used to measure the effectiveness of a test set in terms of its ability to detect faults.

2.2k26.2M1.8k](/packages/infection-infection)[mailgun/mailgun-php

The Mailgun SDK provides methods for all API functions.

1.1k28.9M168](/packages/mailgun-mailgun-php)[driftingly/rector-laravel

Rector upgrades rules for Laravel Framework

1.2k12.0M462](/packages/driftingly-rector-laravel)[veewee/xml

XML without worries

1835.9M29](/packages/veewee-xml)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
