What Strategy-First Actually Bought Them
An honest retrospective on fifteen parts of source-reading - what the decision records bought, what they could not buy, and the compliance gaps nobody wrote down.
Newest first, grouped by year. Search or filter by topic.
An honest retrospective on fifteen parts of source-reading - what the decision records bought, what they could not buy, and the compliance gaps nobody wrote down.
Four decision records with a named reporter and approver, no dates, no supersession, an architecture board hosted outside version control and a README that links code by line number.
Two events in GroupFlights have more than one subscriber, and both are where it breaks - two handlers ask "is this mine?" and two do not, in both directions.
A fully built cross-cutting decorator disables an entire context relationship behind a local variable that is always false - while a sibling module enforces the identical rule for real.
The event interface has no members, so nothing can carry a correlation id - and three modules each rebuild the pattern as application state, one of them in a static dictionary with a TODO.
ADR 04 extracts the reservation-change process out of Sales, lists ten steps and two recommendations - and nine of the ten steps are traceable to real code.
ADR 04 names one risk in prose - changing a reservation on stale information - and the table built to mitigate it has no version, no timestamp and no concurrency check.
One published type from the Communication module is mapped as an owned entity into TimeManagement's schema - so adding a field to your own contract now needs a migration you do not own.
Seven of thirteen published integration events in GroupFlights have exactly one consumer - the module that published them - and one has none at all.
ADR 01 chose a verbal ban on illegal project references over an automated architecture test - and the ban held perfectly, in an estate whose database boundary has no enforcement at all.
Seven contract projects are the estate's entire cross-module surface - and one misplaced marker interface drags the dispatcher framework into two of them by copy-paste.
Three of the ten contexts on the context map have no code behind them - and reading the absences carefully separates a design placeholder from a forgotten promise.
A repeatable twenty-minute method for deriving a real context map from the project graph and the event subscriptions - then diffing it against the one on the wall.
ADR 03 declares six relationship patterns across ten bounded contexts and gives a reason for each - read on its own terms, before any code is checked against it.
GroupFlights picks a different application architecture per module on purpose - and the module nobody singled out turns out to hold the only real aggregate in the estate.
Most repositories ship code and a README - this one ships four ADRs with a named approver, a context map, a domain message flow and a methodology poster. Part 1 of a series that reads the strategic half of DevMentors' GroupFlights.
ModularMonolith's entities are public-setter data bags, its one immutability rule is a fixup with a comment, and its hardest domain question is asked in a comment and answered by nothing - a reading of domain modelling by annotation.
AssignVehicleToOrder is the one command in Pacco that cannot finish alone - Orders calls Vehicles, then Pricing, and Pricing calls Customers, a synchronous enrichment chain on the write path of a messaging estate. At the end of it sits a deliberately bus-less calculator with a loyalty ladder, an unassigned Id and a discount logged in dollars.
The series retrospective - Pacco's domain teaches real rules (state machines, priority expropriation, loyalty ladders, compensations) on top of cardboard data (bare-decimal prices, one vehicle per order, size-cube parcels, no payment, and a capacity check that ships in two halves nobody ever connects). What to steal, what to distrust, and what fourteen parts of source-reading add up to.
Availability guards every save with a version-filtered ReplaceOneAsync - and discards the result, so a lost update is indistinguishable from a successful one and the integration event ships either way. Three folders away, Orders and Customers inherit the same AggregateRoot name with the versioning quietly deleted.
In Pacco the CQRS split is not a diagram - it is wiring you can read. Every command arrives through two front doors, RabbitMQ subscription and controller-less HTTP dispatch, while queries ride HTTP only; commands assign their own ids in the constructor, and a marker attribute turns each service into its own runtime contract registry.
Every Pacco service that enables Convey's Mongo outbox also sets disableTransactions to true - the aggregate write and the outbox write are separate operations, the pattern's one guarantee switched off in configuration. Meanwhile the inbox that would absorb the resulting duplicates sits beside three handlers that throw on them.
Four Pacco services need customer data and no two agree on how to get it - Orders and Parcels keep id-only replicas fed by events, Availability phones home mid-command, and Pricing pulls the full details document to count one number. One upstream, three consistency stances, five representations of the same entity.
Inside the Customers service a registration completes - and the rest of the estate hears that a customer was created. Three lines of EventMapper perform the best ubiquitous-language translation in Pacco, sitting on top of a lifecycle state machine with one guarded transition and four administrative jumps.
Order.DeleteParcel raises a ParcelDeleted event and never removes the parcel from the set, while Parcels' cancel and delete handlers detach exactly one parcel of many. Two bounded contexts maintain the same association independently, both with bugs, and end up permanently disagreeing about a fact.