domain language — service composition
Service composition — the backend discipline
How services talk to each other is an architectural decision — made in the ADR, not discovered in the code. Two patterns dominate, and choosing the wrong one produces failures that look like bugs but are actually architecture errors:
- Request-response — one service calls another and waits. Synchronous, simple, traceable. Right for: queries, user-facing operations where latency matters, anything that needs an immediate answer.
- Event-driven — one service publishes an event; others react. Asynchronous, decoupled, harder to trace. Right for: side effects that don't affect the user's immediate experience, cross-context updates, audit trails.
For Uri's billing Epic, the charge attempt is request-response (the user's billing status depends on the answer). The notification that a charge failed is event-driven (the email can arrive minutes later without affecting the billing flow). The choice is made in the ADR, reflected in the API contract, and enforced in the code. Changing it later is expensive because tests, contracts, and monitoring all assume the pattern.
Developer experience as chain investment
Developer experience (DX) is not a luxury. It is the infrastructure that determines how fast a developer can go from pulling a story to pushing a commit — and how many friction points they hit along the way. Every friction point is a moment where the developer's attention shifts from the person's situation to the system's tooling. Enough friction, and the developer stops thinking about Gal and starts thinking about the build system.
The investments that matter:
- Local dev setup that works in under 15 minutes from a fresh clone.
- Hot reload so changes are visible without restarting.
- Type safety so domain-language errors are caught at compile time, not at runtime.
- Linting rules that enforce domain naming and commit format automatically.
- Storybook as the component development environment.
Each one is a small investment that compounds across every story the team pulls.
Resolution gate — Domain to Pipeline
Enough to write code that speaks the brief.
The domain language is consistent from brief to code. Bounded context boundaries are named in the API contracts. The component library matches the design system. Local dev works.
Test: a developer reading a function name, a test name, and a component name can trace each one back to the brief without opening Confluence.