Microservices: deep modules and boundaries
Vova likes that Vlad opens every chapter of this part with how to hurt yourself — with microservices, events, analytics — and only then shows how DDD helps. A service is defined abstractly: a unit with business logic and an interface, and a system is never a set of independent pieces — they still talk, and how that communication is arranged decides the rest of their life. Cutting a large service by methods yields a distributed big ball of mud: local complexity drops, global complexity grows, and instead of a front door every house sprouts a crowd of back doors. Vova recalls a hire in a neighbouring unit who within a month demanded a service per method and could not be talked out of it — poor knowledge of microservices can cost a career. The participants call microservices a business model: distributed autonomous teams, frequent deploys, thousands of engineers in different languages — a monolith no longer fits that.
Alexander unpacks the deep-modules metaphor from John Ousterhout's book, which Vlad borrows: the more complexity hides behind a narrow interface, the lower the system's overall complexity, while small modules with wide interfaces raise it. On the parabola of change cost against granularity both ends are expensive — the monolith and the distributed monolith with its web of back doors — and microservices look for the trade-off at the bottom. Then the DDD tools as boundaries: every microservice is a bounded context, but not every context is a microservice; aggregates as boundaries are too fine and resemble splitting by function unless aggregates talk constantly, in which case they are kept together; subdomains are the safer option, though Vova Ivanov sees the temptation to slice them too thin. Alexander reminds that subdomains are discovered, not designed, and adds the promises made to the business — SLAs, reliability, roadmaps — to the technical criteria. His example is a system that served content for acquisition pages and, at the same time, news for the investment app: a small news feature took the service down, an hour without acquisition pages cost millions of roubles, and the system was then cut by the importance of its domains.
Event-driven architecture without the traps
Ilya recalls the architecture quantum from Ford's book: asynchronous interaction lets parts of the system ship independently. Vlad separates messages into events and commands — Vova brings the example from the Kleppmann sessions: a user asks for a login, a taken one is rejected as a command, a free one produces the event "user created". Three kinds of events: a notification with an identifier and a link for details — safer, helpful for concurrency because consumers fetch fresh data under a lock, and easier for GDPR deletion; event-carried state transfer — a full snapshot or only the changed fields, from which the consumer builds a local replica, much like CDC but in a shape the producer prepares itself; and a domain event — say, a flag that one spouse changed their surname — which describes a business fact in the object's lifecycle and is not meant for integrating services: one such event is never enough for integration.
The chapter's main example is a reporting service that waits five minutes on a timer for the optimisation service to process an event and only then fetches the data; Vova has seen exactly that in the wild. Vlad breaks the coupling down into functional (two services do the same work), temporal (you have to wait), and implementation coupling (a new event type breaks everyone). The cure is an open host with public events separated from domain events, a minimal outward interface, and a notification from the optimisation service on which reporting collects the finished data itself. The closing heuristics: expect the worst — the network will fail, services will crash, events will arrive out of order, and consumers must survive that. Alexander points out that "only the paranoid survive" is Andy Grove's book about Intel's crises — leaving memory for processors, and the Pentium arithmetic bug that raised a user revolt Intel had no channels to hear. And the advice: private and public events, domain events rarely exposed, notifications where the consumer needs strongly consistent data.
From DWH and data lake to data mesh
Alexander opens the analytics chapter, which he recommends to anyone who has thought about the topic: an analytical model serves insights and predictions, a transactional one serves user requests quickly, and they are stored differently. Vlad recaps the star and snowflake schemas: a fact table and dimensions, the latter with multi-level normalisation that saves storage but pays in joins. The data warehouse is the old approach that works up to a point: ETL scripts pull data from transactional systems, transform it on the fly, and load it into a single enterprise model. The trouble is that a single consistent model for the whole company never comes together, data marts multiply, and the ETL scripts know the services' internals and go stale with every feature: either the reports break or development freezes. Alexander describes how a new product first has no proper reporting, and then the reports that appear stop features from shipping without breaking them.
The data lake gives up the magic model: raw data is exported as is and transformed per task, but data quality drifts, service encapsulation is still broken, and the number of scripts is endless; data engineers in a separate unit know nothing of the business and keep fixing collapsed reports, and DDD systems, where the model changes often, suffer most. Hence data mesh — Alexander heard its author, then a principal consultant at ThoughtWorks, at a conference in 2019: it is DDD for analytical data. Four principles: data is organised around domains and owned by the bounded-context teams, which need an engineer of their own; data is a first-class product with a clear, versioned schema and quality agreements — a published language; team autonomy through a data platform; and federated governance so that autonomy does not become anarchy. Vova Ivanov confirms: their analytical data is described with Avro schemas and published to Kafka. Vlad closes with the ubiquitous language, CQRS for multiple models, and the context-integration patterns all applying to analytics. The next episode is with the author.
What to take away
- 01Microservices are cut by bounded contexts and subdomains, not by methods: deep modules with narrow interfaces lower overall complexity, while a service per method yields a distributed ball of mud.
- 02Notification, event-carried state transfer, and domain events solve different problems; domain events are about an object's lifecycle, not about integrating services.
- 03Event coupling comes as functional, temporal, and implementation coupling; the cure is an open host with public events and paranoia: the network will fail and order will break.
- 04DWH and data lake break on ETL scripts that know service internals; data mesh brings DDD to analytics — data as a domain team's product with a published schema.