DDD、CQRS/ES与微服务:决策基于视图还是聚合?
air-miles microservice use its local view model for reward decisions? First, let's recap the architecture constraints and example to ground our discussion:
Our microservice setup follows this strict rule: 1 MicroService <=> 1 Aggregate <=> Transactional Boundary, with every service built using CQRS/Event Sourcing (ES). Key characteristics include:
- Each service owns a domain-specific Aggregate mapped directly to real-world business logic
- Aggregate state is fully reconstructed from its dedicated event store
- State changes are propagated as events via message queues to dependent services
- Transactions are guaranteed only within a service's own domain boundary
- Cross-service consistency is eventual, not immediate
- Each service builds its own optimized view models using events emitted by other services
Using the banking example provided:
- The
current-accountservice handles all checking account deposits, withdrawals, and core transaction logic - The
rewardsservice manages bank reward inventory, availability, and issuance rules - The
air-milesservice monitorscurrent-accounttransactions to trigger reward issuance for customers
Core Question
Should the air-miles service rely on its locally maintained view model (updated from current-account events) to make critical decisions—like determining which rewards to issue to a customer?
Option 1: Decide Using the Local View Model
Pros
- No ongoing dependency on source services: You avoid the latency and availability risk of querying
current-accountevery time a decision needs to be made - Better performance & resource efficiency: Local view models are optimized for fast read access, so decisions can be processed quickly without network overhead
- Decoupled operation:
air-milescan continue functioning even ifcurrent-accountexperiences short-term outages, as long as its view model is up-to-date
Cons
- Redundant domain logic: You’ll have to re-implement and maintain the same transaction validation rules that
current-accountalready enforces. This duplicates effort and creates inconsistency risks if rules are updated in one service but not the other - Bug & corruption ripple effects: If the view model has a bug (e.g., miscalculating transaction eligibility) or becomes corrupted (e.g., missing events), you’ll issue incorrect rewards. Worse, any events emitted by
air-milesbased on bad data will propagate to other dependent services, amplifying the failure - Stale data risks: Even with reliable event delivery, there’s a window where the local view might not reflect the latest state in
current-account, leading to decisions based on outdated information
Option 2: Trigger Queries to the Source Domain Aggregate
This approach uses current-account events as triggers, but always consults the current-account service’s Aggregate directly for the authoritative state needed to make reward decisions. You accept that the local view model might be stale, but anchor all critical decisions to the source of truth.
Key Tradeoffs
- Stronger decision integrity: You eliminate the risk of relying on stale or corrupted local data—decisions are based on the definitive state from
current-account - Increased latency & dependency: Every decision requires a cross-service call, which adds latency and introduces a point of failure if
current-accountis unavailable - Simpler maintenance: No need to duplicate domain logic from
current-account—you trust the source service to enforce its own rules, reducing long-term maintenance overhead
Perspectives to Guide Your Choice
Here are different angles to consider when weighing these options:
- Business impact of errors: If issuing incorrect rewards has severe consequences (e.g., regulatory fines, customer churn), prioritizing the source Aggregate query approach makes sense. The cost of occasional latency is worth avoiding cascading failures and bad decisions.
- Event pipeline reliability: If your message queue and event processing system have strong guarantees (e.g., exactly-once delivery, no event loss, automated replay for missed events), the risk of view model corruption drops significantly. In this case, using the local view might be acceptable for low-stakes decisions.
- Scalability needs: If
air-milesneeds to handle extremely high throughput, the overhead of cross-service calls could become a bottleneck. Here, optimizing for local view models (with safeguards like periodic validation against the source Aggregate) might be necessary. - Domain ownership alignment: Sticking to the source Aggregate aligns with the core principle of "single source of truth"—each domain owns its state and logic, so other services shouldn’t replicate or second-guess it. This keeps the system aligned with your original architecture rules.
Content sourced from Stack Exchange, question author MrX

