Domain model metrics turn "the split feels wrong" into something you can check: how many teams one change drags in, which arrows point the wrong way, why lines of code lie inside aggregates, and why you should sketch four models before picking one.
Generation got a hundred times faster and reading did not. What that actually breaks in code review, why spec-driven development collapses into a compiler, why clean code matters more when agents read it, and what to build instead: an ontology of your own development process.
Business archetypes prove your 'unique' domain is usually a store selling something unusual. Map complex requirements onto universal building blocks: product catalogue, orders, entitlements, inventory for services, party and billing, and stop reinventing the wheel.
Pseudo-modularity looks like clean folders and rots underneath: a change in Products breaks Inventory tests and blocks three teams. Why noun-driven modules and a shared database create facade modularity, and what real module boundaries look like.
Module boundaries should come from simulation, not subdomain divination. An engineering method for DDD: optimise for modifiability, simulate realistic changes against candidate boundaries, prove the split with stable contracts, and explain it to the business.
Event-driven architecture with Kafka can still be a distributed monolith. The anti-patterns that get you there: CRUD sourcing, property sourcing, clickbait events, missing commands, and the fixes: rich events, outbox, internal vs external events, anti-corruption layers.
Siamese twin modules force a change in one place to ripple into another. How domain leakage and state-transfer events create a distributed monolith, and how contextual modularization with the right communication patterns cuts the connection, without cargo cult.
DDD is not aggregates first: the discovery process is the heart of it. Why strategy with domain experts beats jumping into tactical patterns, the language pitfalls that derail modelling, the 'what if' trap, and why change must come from above and below.
Event Sourcing can be introduced to legacy systems incrementally, no big rewrite required. Lessons from production: the migration event technique, upcasting old events, right-sizing aggregates, stream lifecycles, and payoffs in audits, analytics, and debugging.
Domain Driven Design in Ruby with a working example: aggregates, entities, value objects, and repositories built around a ProductCatalog, then extended with event-driven design and event sourcing, where projections rebuild state from events instead of a database.